#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;   }