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 Maxn = 50020, Inf = 1e9 + 7;
int n, m, tot;
int tl[Maxn], col[Maxn];
int uu[Maxn], vv[Maxn];
bool cmp(int a, int b) { return col[a] < col[b]; }
vector<int> G[Maxn];
vector<int> G2[Maxn << 4];
vector<int> rep;
bool mark[Maxn << 4];
int top, S[Maxn << 4];
bool dfs(int u) {
  if (mark[u ^ 1]) return 0;
  if (mark[u]) return 1;
  mark[u] = 1;
  S[top++] = u;
  for (int i = 0; i < G2[u].size(); i++) {
    if (!dfs(G2[u][i])) return 0;
  }
  return 1;
}
bool check(int Tl, int ptmod = 0) {
  for (int i = 0; i < tot << 1; i++) mark[i] = 0;
  for (int i = 0; i < m; i++) {
    if (tl[i] > Tl) {
      if (mark[i << 1]) return 0;
      if (mark[i << 1 | 1]) continue;
      if (!dfs(i << 1 | 1)) return 0;
    }
  }
  for (int i = 0; i < m; i++) {
    if (!mark[i << 1] && !mark[i << 1 | 1]) {
      if (!dfs(i << 1)) {
        while (top) mark[S[--top]] = 0;
        if (!dfs(i << 1 | 1)) return 0;
      } else {
        if (ptmod) rep.push_back(i);
      }
    } else if (mark[i << 1] && ptmod)
      rep.push_back(i);
  }
  if (ptmod) {
    puts("Yes");
    printf("%d %d\n", Tl, (int)rep.size());
    for (int i = 0; i < rep.size(); i++)
      printf("%d%c", rep[i] + 1, i == rep.size() ? '\n' : ' ');
  }
  return 1;
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < m; i++) {
    scanf("%d%d%d%d", uu + i, vv + i, col + i, tl + i);
    G[uu[i]].push_back(i);
    G[vv[i]].push_back(i);
  }
  bool flag = 1;
  tot = m;
  for (int i = 1; i <= n && flag; i++) {
    vector<int>& V = G[i];
    sort(V.begin(), V.end(), cmp);
    for (int j = 0, k; j < V.size(); j = k) {
      vector<int> tp;
      for (k = j; k < V.size() && col[V[k]] == col[V[j]]; k++)
        tp.push_back(V[k]);
      if (tp.size() > 2) {
        flag = false;
        break;
      }
      if (tp.size() == 2) {
        G2[tp[0] << 1 | 1].push_back(tp[1] << 1);
        G2[tp[1] << 1 | 1].push_back(tp[0] << 1);
      }
    }
    vector<int> pre, suf;
    for (int j = 0; j < V.size(); j++) {
      int t = tot++;
      pre.push_back(t);
      G2[t << 1].push_back(V[j] << 1);
      G2[t << 1 | 1].push_back(V[j] << 1 | 1);
      if (j)
        G2[t << 1].push_back((t - 1) << 1),
            G2[t << 1 | 1].push_back((t - 1) << 1 | 1);
    }
    for (int j = V.size() - 1; j >= 0; j--) {
      int t = tot++;
      suf.push_back(t);
      G2[t << 1].push_back(V[j] << 1);
      G2[t << 1 | 1].push_back(V[j] << 1 | 1);
      if (j < V.size() - 1)
        G2[t << 1].push_back((t - 1) << 1),
            G2[t << 1 | 1].push_back((t - 1) << 1 | 1);
    }
    reverse(suf.begin(), suf.end());
    for (int j = 0; j < V.size(); j++) {
      int t = V[j];
      if (j) G2[t << 1].push_back(pre[j - 1] << 1 | 1);
      if (j < V.size() - 1) G2[t << 1].push_back(suf[j + 1] << 1 | 1);
    }
  }
  if (tot >= (Maxn << 4))
    while (1)
      ;
  if (m > 40000) return 0;
  if (!flag || !check(Inf)) {
    puts("No");
    return 0;
  }
  if (check(0)) {
    puts("Yes");
    puts("0 0");
    return 0;
  }
  int L = 0, R = Inf;
  while (L + 1 < R) {
    int mid = (L + R) >> 1;
    if (check(mid))
      R = mid;
    else
      L = mid;
  }
  check(R, 1);
}
