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;
int n, m, cnt, b[1000100], dfn[1000100], low[1000100], q[1000100], tot, top,
    sccflag[1000100], pre[1000100], nxt[1000100];
int cnt2, cnt3, cntc;
int cntans, ans[1000100];
vector<int> p[1000100];
struct edge {
  int v;
  edge *next;
} pool[2 * 1000100], *h[1000100];
void addedge(int u, int v) {
  edge *p = &pool[++cnt];
  p->v = v;
  p->next = h[u];
  h[u] = p;
}
struct node {
  int u, v, c, w, id;
} a[1000100];
void tarjan(int u) {
  dfn[u] = low[u] = ++tot;
  q[++top] = u;
  int v;
  for (edge *p = h[u]; p; p = p->next) {
    if (dfn[p->v] == 0) {
      tarjan(p->v);
      low[u] = min(low[u], low[p->v]);
    } else if (sccflag[p->v] == 0)
      low[u] = min(low[u], dfn[p->v]);
  }
  if (dfn[u] == low[u]) {
    cntc++;
    while (q[top + 1] != u) {
      sccflag[q[top]] = cntc;
      top--;
    }
  }
}
bool cmp(node x, node y) { return x.w < y.w; }
bool cmp2(int x, int y) {
  if (a[x].c != a[y].c)
    ;
  return a[x].c < a[y].c;
  return a[x].w < a[y].w;
}
bool check(int mid) {
  memset(h, 0, sizeof(h));
  memset(pool, 0, sizeof(pool));
  cnt = 0;
  for (int i = 1; i <= m; i++) {
    if (a[i].w > mid) {
      addedge(i, i + m);
    }
  }
  cnt2 = 2 * m;
  for (int k = 1; k <= n; k++) {
    cnt3 = 0;
    for (int i = 0; i < p[k].size(); i++) b[++cnt3] = p[k][i];
    sort(b + 1, b + cnt3 + 1, cmp2);
    for (int i = 1; i <= cnt3; i++) pre[i] = ++cnt2, nxt[i] = ++cnt2;
    for (int i = 1; i <= cnt3 - 1; i++)
      addedge(pre[i], pre[i + 1]), addedge(pre[i], b[i + 1] + m);
    for (int i = 2; i <= cnt3; i++)
      addedge(nxt[i], nxt[i - 1]), addedge(b[i], nxt[i - 1]);
    for (int i = 1; i <= cnt3; i++)
      addedge(b[i], pre[i]), addedge(nxt[i], b[i] + m);
    for (int i = 1; i <= cnt3; i++) pre[i] = ++cnt2, nxt[i] = ++cnt2;
    for (int i = 1; i <= cnt3; i++) {
      int R = i;
      while (R < cnt3 && a[b[R + 1]].c == a[b[i]].c) R++;
      for (int j = i; j <= R; j++) {
        addedge(pre[j], b[j]);
        addedge(b[j] + m, nxt[j]);
        if (j != R) {
          addedge(nxt[j], b[j + 1]);
          addedge(b[j + 1] + m, pre[j]);
          addedge(pre[j + 1], pre[j]);
          addedge(nxt[j], nxt[j + 1]);
        }
      }
      i = R;
    }
  }
  tot = top = cntc = 0;
  for (int i = 1; i <= cnt2; i++) dfn[i] = low[i] = sccflag[i] = 0;
  for (int i = 1; i <= cnt2; i++) {
    if (dfn[i] == 0) tarjan(i);
  }
  for (int i = 1; i <= m; i++) {
    if (sccflag[i] == sccflag[i + m]) return false;
  }
  return true;
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++)
    scanf("%d%d%d%d", &a[i].u, &a[i].v, &a[i].c, &a[i].w), a[i].id = i;
  sort(a + 1, a + m + 1, cmp);
  for (int i = 1; i <= m; i++) {
    p[a[i].u].push_back(i);
    p[a[i].v].push_back(i);
  }
  int left = 0, right = 1000000000, mid, Ans = -1;
  while (left <= right) {
    mid = (left + right) / 2;
    if (check(mid) == true)
      right = mid - 1, Ans = mid;
    else
      left = mid + 1;
  }
  if (Ans == -1) {
    printf("No\n");
    return 0;
  }
  bool Mo = check(Ans);
  for (int i = 1; i <= m; i++) {
    if (sccflag[i] < sccflag[i + m]) ans[++cntans] = a[i].id;
  }
  printf("Yes\n");
  printf("%d %d\n", Ans, cntans);
  for (int i = 1; i <= cntans; i++) {
    printf("%d ", ans[i]);
  }
  return 0;
}
