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 = 1e5 + 10;
int rd() {
  int x = 0, w = 1;
  char ch = 0;
  while (ch < '0' || ch > '9') {
    if (ch == '-') w = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = (x << 3) + (x << 1) + (ch ^ 48);
    ch = getchar();
  }
  return x * w;
}
int to[N * 80], nt[N * 80], hd[N << 4], tot = 1, ee[N * 80][2], te, dg[N << 4];
void adde(int x, int y) {
  ee[++te][0] = x, ee[te][1] = y;
  ++tot, to[tot] = y, nt[tot] = hd[x], hd[x] = tot;
}
void ade(int x, int y) { ++tot, to[tot] = y, nt[tot] = hd[x], hd[x] = tot; }
int n, m, co[N], w[N], pz[N], pt, an[N], ta;
vector<int> ze[N];
bool cmp(int aa, int bb) { return co[aa] < co[bb]; }
int dfn[N << 4], low[N << 4], ti, st[N << 4], tp, po[N << 4], va[N << 4],
    ps[N << 4], ts;
bool vs[N << 4];
void tj(int x) {
  dfn[x] = low[x] = ++ti, st[++tp] = x, vs[x] = 1;
  for (int i = hd[x]; i; i = nt[i]) {
    int y = to[i];
    if (!dfn[y])
      tj(y), low[x] = min(low[x], low[y]);
    else if (vs[y])
      low[x] = min(low[x], low[y]);
  }
  if (dfn[x] == low[x]) {
    while (tp) {
      int y = st[tp--];
      po[y] = x, vs[y] = 0;
      if (x == y) break;
    }
  }
}
struct node {
  int sh, i;
  bool operator<(const node &bb) const { return sh > bb.sh; }
};
priority_queue<node> q;
int main() {
  n = rd(), m = rd();
  for (int i = 1; i <= m; ++i) {
    ze[rd()].push_back(i), ze[rd()].push_back(i);
    co[i] = rd(), w[i] = rd();
  }
  pt = m + m;
  for (int i = 1; i <= n; ++i) {
    sort(ze[i].begin(), ze[i].end(), cmp);
    int nn = ze[i].size();
    if (!nn) continue;
    tp = 0;
    for (int j = 0, k = 0; j < nn;) {
      while (k < nn - 1 && co[ze[i][k + 1]] == co[ze[i][j]]) ++k;
      if (j < k) {
        pz[j] = ++pt, adde(pz[j], ze[i][j]);
        for (int l = j + 1; l <= k; ++l) {
          if (l < k)
            pz[l] = ++pt, adde(pz[l], pz[l - 1]), adde(pz[l], ze[i][l]);
          adde(ze[i][l] + m, pz[l - 1]);
        }
        pz[k] = ++pt, adde(pz[k], ze[i][k]);
        for (int l = k - 1; l >= j; --l) {
          if (l > j)
            pz[l] = ++pt, adde(pz[l], pz[l + 1]), adde(pz[l], ze[i][l]);
          adde(ze[i][l] + m, pz[l + 1]);
        }
      }
      j = k + 1;
    }
    pz[0] = ++pt, adde(pz[0], ze[i][0] + m);
    for (int l = 1; l < nn; ++l) {
      if (l < nn - 1)
        pz[l] = ++pt, adde(pz[l], pz[l - 1]), adde(pz[l], ze[i][l] + m);
      adde(ze[i][l], pz[l - 1]);
    }
    pz[nn - 1] = ++pt, adde(pz[nn - 1], ze[i][nn - 1] + m);
    for (int l = nn - 2; ~l; --l) {
      if (l > 0)
        pz[l] = ++pt, adde(pz[l], pz[l + 1]), adde(pz[l], ze[i][l] + m);
      adde(ze[i][l], pz[l + 1]);
    }
  }
  for (int i = 1; i <= pt; ++i)
    if (!dfn[i]) tj(i);
  for (int i = 1; i <= m; ++i)
    if (po[i] == po[i + m]) {
      puts("No");
      return 0;
    }
  memset(hd, 0, sizeof(int) * (pt + 1)), tot = 1;
  for (int i = 1; i <= te; ++i) {
    int x = po[ee[i][0]], y = po[ee[i][1]];
    if (x != y) ade(x, y), ++dg[y];
  }
  for (int i = 1; i <= m; ++i) {
    va[po[i + m]] = max(va[po[i + m]], w[i]);
  }
  for (int i = 1; i <= pt; ++i)
    if (po[i] == i && !dg[i]) q.push((node){va[i], i});
  while (!q.empty()) {
    int x = q.top().i;
    q.pop();
    ps[x] = ++ts;
    for (int i = hd[x]; i; i = nt[i]) {
      int y = to[i];
      --dg[y];
      if (!dg[y]) q.push((node){va[y], y});
    }
  }
  int ans = 0;
  for (int i = 1; i <= m; ++i)
    if (ps[po[i]] > ps[po[i + m]]) {
      ans = max(ans, w[i]);
      an[++ta] = i;
    }
  puts("Yes");
  printf("%d %d\n", ans, ta);
  for (int i = 1; i <= ta; ++i) printf("%d ", an[i]);
  return 0;
}
