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;
stack<int> S;
int n, m, AS;
int as[400005];
int ur[50005], vr[50005], cl[50005], t[50005], e;
struct graph {
  int dn[400005], lw[400005], vs[400005], bl[400005];
  int bh, nm, hd[400005], vr[1600005], nt[1600005], tt;
  void push(int x, int y) {
    vr[++tt] = y;
    nt[tt] = hd[x];
    hd[x] = tt;
  }
  void dfs(int nw) {
    S.push(nw);
    vs[nw] = 1;
    dn[nw] = lw[nw] = ++bh;
    for (int i = hd[nw]; i; i = nt[i]) {
      if (!dn[vr[i]]) {
        dfs(vr[i]);
        lw[nw] = min(lw[nw], lw[vr[i]]);
      } else if (vs[vr[i]])
        lw[nw] = min(lw[nw], dn[vr[i]]);
    }
    if (dn[nw] == lw[nw]) {
      ++nm;
      while (S.top() != nw) bl[S.top()] = nm, vs[S.top()] = 0, S.pop();
      bl[nw] = nm;
      S.pop();
      vs[nw] = 0;
    }
  }
  void tarjan() {
    memset(dn, 0, sizeof(dn));
    memset(lw, 0, sizeof(lw));
    memset(vs, 0, sizeof(vs));
    memset(bl, 0, sizeof(bl));
    nm = bh = 0;
    for (int i = (1); i <= (e); ++i)
      if (!dn[i]) dfs(i);
  }
  int check() {
    tarjan();
    for (int i = (1); i <= (m); ++i)
      if (bl[i] == bl[i + m]) return 0;
    AS = 0;
    for (int i = (1); i <= (m); ++i)
      if (bl[i] < bl[i + m])
        as[i] = 1, ++AS;
      else
        as[i] = 0;
    return 1;
  }
} G;
struct basic_graph {
  int hd[400005], vr[1600005], nt[1600005], tt;
  void push(int x, int y) {
    vr[++tt] = y;
    nt[tt] = hd[x];
    hd[x] = tt;
  }
  void build_G(int md) {
    memcpy(G.hd, hd, sizeof(hd));
    memcpy(G.vr, vr, sizeof(vr));
    memcpy(G.nt, nt, sizeof(nt));
    G.tt = tt;
    for (int i = (1); i <= (m); ++i)
      if (t[i] > md) G.push(i, i + m);
  }
} BG;
struct old_graph {
  map<int, int> vs;
  int hd[50005], vr[100005], vl[100005], nt[100005], tt;
  void push(int x, int y, int z) {
    vr[++tt] = y;
    vl[tt] = z;
    nt[tt] = hd[x];
    hd[x] = tt;
  }
  int fp[100005];
  void build_BG() {
    e = 2 * m;
    for (int i = (1); i <= (n); ++i) {
      for (int j = hd[i]; j; j = nt[j]) {
        if (!vs[vl[j]])
          vs[vl[j]] = vr[j];
        else if (vs[vl[j]] == -1) {
          cout << "No" << endl;
          exit(0);
        } else {
          BG.push(vr[j] + m, vs[vl[j]]);
          BG.push(vs[vl[j]] + m, vr[j]);
          BG.push(vr[j], vs[vl[j]] + m);
          BG.push(vs[vl[j]], vr[j] + m);
          vs[vl[j]] = -1;
        }
      }
      for (int j = hd[i]; j; j = nt[j]) vs[vl[j]] = 0;
      int fc = 0;
      for (int j = hd[i]; j; j = nt[j]) {
        S.push(j);
        if (fc) BG.push(vr[j], fp[fc]);
        fp[++fc] = ++e;
        if (fc - 1) BG.push(fp[fc], fp[fc - 1]);
        BG.push(fp[fc], vr[j] + m);
      }
      fc = 0;
      while (S.size()) {
        int j = S.top();
        S.pop();
        if (fc) BG.push(vr[j], fp[fc]);
        fp[++fc] = ++e;
        if (fc - 1) BG.push(fp[fc], fp[fc - 1]);
        BG.push(fp[fc], vr[j] + m);
      }
    }
  }
} OG;
int main() {
  scanf("%d%d", &n, &m);
  for (int i = (1); i <= (m); ++i) {
    scanf("%d%d%d%d", &ur[i], &vr[i], &cl[i], &t[i]);
    OG.push(ur[i], i, cl[i]);
    OG.push(vr[i], i, cl[i]);
  }
  OG.build_BG();
  int l = 0, r = 1000000000 + 1, md;
  while (l < r) {
    md = (l + r) >> 1;
    BG.build_G(md);
    if (G.check())
      r = md;
    else
      l = md + 1;
  }
  if (l == 1000000001) {
    cout << "No" << endl;
    return 0;
  }
  cout << "Yes" << endl;
  cout << r << " " << AS << endl;
  for (int i = (1); i <= (m); ++i)
    if (as[i]) printf("%d ", i);
}
