3 5
2 1 608591421 720962564
3 2 608591421 641991574
3 2 718110706 353409763
2 3 482786015 858341723
3 2 825397574 357507279
 2 1
2 1 317425595 636156322
 50000 1
20845 28516 904146168 997637433

Yes
641991574 1
2 
 Yes
0 0

 Yes
0 0


#include <bits/stdc++.h>
using namespace std;
const int N = 500010;
vector<int> v[N], e[N];
int cnt;
struct point {
  int u, v, c, t;
  void read() { cin >> u >> v >> c >> t; }
} a[N];
bool cmp(int x, int y) { return a[x].c < a[y].c; }
void build1(int l, int r, int id, int m) {
  int p = -1, q = -1;
  for (int i = l; i <= r; i++) {
    int x = v[id][i];
    int y = x + m;
    int pp = ++cnt;
    int qq = ++cnt;
    e[x].push_back(pp);
    e[qq].push_back(y);
    if (p != -1) {
      e[p].push_back(pp);
      e[qq].push_back(q);
      e[p].push_back(y);
      e[x].push_back(q);
    }
    p = pp, q = qq;
  }
}
void build2(int l, int r, int id, int m) {
  int p = -1, q = -1;
  for (int i = l; i <= r; i++) {
    int x = v[id][i];
    int y = x + m;
    int pp = ++cnt;
    int qq = ++cnt;
    e[pp].push_back(x);
    e[y].push_back(qq);
    if (p != -1) {
      e[pp].push_back(p);
      e[q].push_back(qq);
      e[y].push_back(p);
      e[q].push_back(x);
    }
    p = pp, q = qq;
  }
}
int dfn[N], low[N];
stack<int> stk;
bool instack[N];
int bel[N], scc, num;
void tarjan(int u) {
  dfn[u] = low[u] = ++num;
  stk.push(u);
  instack[u] = true;
  for (int i = 0; i < e[u].size(); i++) {
    int x = e[u][i];
    if (!dfn[x]) {
      tarjan(x);
      low[u] = min(low[u], low[x]);
    } else if (instack[x])
      low[u] = min(low[u], dfn[x]);
  }
  if (dfn[u] == low[u]) {
    scc++;
    while (true) {
      int x = stk.top();
      stk.pop();
      bel[x] = scc;
      instack[x] = false;
      if (x == u) break;
    }
  }
}
bool check(int t, int m) {
  for (int i = 1; i <= m; i++)
    if (a[i].t > t) e[i].push_back(i + m);
  memset(dfn, 0, sizeof(dfn));
  memset(low, 0, sizeof(low));
  memset(instack, false, sizeof(instack));
  while (!stk.empty()) stk.pop();
  for (int i = 1; i <= cnt; i++)
    if (!dfn[i]) tarjan(i);
  for (int i = 1; i <= m; i++)
    if (a[i].t > t) e[i].pop_back();
  for (int i = 1; i <= m; i++)
    if (bel[i] == bel[i + m]) return false;
  return true;
}
int main() {
  ios::sync_with_stdio(false);
  int n, m;
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    a[i].read();
    v[a[i].u].push_back(i);
    v[a[i].v].push_back(i);
  }
  cnt = 2 * m;
  for (int i = 1; i <= n; i++) {
    sort(v[i].begin(), v[i].end(), cmp);
    build1(0, (int)v[i].size() - 1, i, m);
    int j = 0;
    while (j < v[i].size()) {
      int k = j;
      while (k < v[i].size() && a[v[i][k]].c == a[v[i][j]].c) k++;
      build2(j, k - 1, i, m);
      j = k;
    }
  }
  int l = 1, r = 1000000000, mid;
  int ans = -1;
  while (l <= r) {
    mid = (l + r) >> 1;
    if (check(mid, m)) {
      ans = mid;
      r = mid - 1;
    } else
      l = mid + 1;
  }
  if (ans == -1) {
    cout << "No" << endl;
    return 0;
  }
  cout << "Yes" << endl;
  check(ans, m);
  vector<int> ret;
  for (int i = 1; i <= m; i++)
    if (bel[i] < bel[i + m]) ret.push_back(i);
  cout << ans << " " << ret.size() << endl;
  for (int i = 0; i < ret.size(); i++) cout << ret[i] << " ";
  cout << endl;
  return 0;
}
