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 maxnv = 1e6;
int nv, n, m;
vector<int> g[maxnv];
void Init(int n) {
  nv = n * 2;
  for (int i = 0; i < nv; ++i) {
    g[i].clear();
  }
}
int dfn[maxnv], clk;
int stk[maxnv], top;
int sccid[maxnv], nscc;
int Tarjan(int u) {
  int low = dfn[u] = clk++;
  stk[top++] = u;
  for (int v : g[u]) {
    if (dfn[v] == -1) {
      low = min(low, Tarjan(v));
    } else if (sccid[v] == -1) {
      low = min(low, dfn[v]);
    }
  }
  if (low == dfn[u]) {
    int v;
    do {
      v = stk[--top];
      sccid[v] = nscc;
    } while (v != u);
    ++nscc;
  }
  return low;
}
void FindScc(void) {
  memset((dfn), (-1), sizeof((dfn)[0]) * (nv));
  memset((sccid), (-1), sizeof((sccid)[0]) * (nv));
  clk = top = nscc = 0;
  for (int i = 0; i < nv; ++i) {
    if (dfn[i] == -1) {
      Tarjan(i);
    }
  }
}
void AddEdge(int u, int v) {
  g[u].push_back(v);
  g[v ^ 1].push_back(u ^ 1);
}
void DelEdge(int u, int v) {
  g[v ^ 1].pop_back();
  g[u].pop_back();
}
bool Solve(void) {
  FindScc();
  for (int i = 0; i < nv; i += 2) {
    if (sccid[i] == sccid[i + 1]) {
      return false;
    }
  }
  return true;
}
const int maxn = 5e4, maxm = 5e4;
struct Edge {
  int u, v, c, t;
  void Read(void) {
    scanf("%d%d%d%d", &u, &v, &c, &t);
    --u;
    --v;
  }
} edge[maxm];
vector<int> adj[maxn];
int main(void) {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < m; ++i) {
    edge[i].Read();
    edge[m + i] = edge[i];
    adj[edge[i].u].push_back(i);
    adj[edge[i].v].push_back(m + i);
  }
  m *= 2;
  for (int i = 0; i < n; ++i) {
    sort(adj[i].begin(), adj[i].end(),
         [](int a, int b) { return edge[a].c < edge[b].c; });
  }
  Init(3 * m);
  int ori = 0, con1 = m, con2 = 2 * m;
  for (int u = 0; u < n; ++u) {
    int s = adj[u].size();
    vector<int> &a = adj[u];
    for (int i = 0; i < s; ++i) {
      AddEdge((ori + a[i]) << 1 | 1, (con1 + a[i]) << 1 | 1);
      if (i + 1 < s) {
        AddEdge((con1 + a[i]) << 1 | 1, (con1 + a[i + 1]) << 1 | 1);
        AddEdge((con1 + a[i]) << 1 | 1, (ori + a[i + 1]) << 1 | 0);
      }
    }
    for (int i = 0; i < s; ++i) {
      AddEdge((ori + a[i]) << 1 | 0, (con2 + a[i]) << 1 | 1);
      if (i + 1 < s && edge[a[i]].c == edge[a[i + 1]].c) {
        AddEdge((con2 + a[i]) << 1 | 1, (con2 + a[i + 1]) << 1 | 1);
        AddEdge((con2 + a[i]) << 1 | 1, (ori + a[i + 1]) << 1 | 1);
      }
    }
  }
  for (int i = 0; i < m / 2; ++i) {
    AddEdge((ori + i) << 1 | 1, (ori + i + m / 2) << 1 | 1);
    AddEdge((ori + i) << 1 | 0, (ori + i + m / 2) << 1 | 0);
  }
  if (!Solve()) {
    puts("No");
    return 0;
  }
  int low = 0, high = 1e9 + 10;
  while (high - low > 1) {
    int mid = low + high >> 1;
    int lim = mid - 1;
    for (int i = 0; i < m; ++i) {
      if (edge[i].t > lim) {
        AddEdge((ori + i) << 1 | 1, (ori + i) << 1 | 0);
      }
    }
    if (Solve()) {
      high = mid;
    } else {
      low = mid;
    }
    for (int i = 0; i < m; ++i) {
      if (edge[i].t > lim) {
        DelEdge((ori + i) << 1 | 1, (ori + i) << 1 | 0);
      }
    }
  }
  puts("Yes");
  int lim = low;
  for (int i = 0; i < m; ++i) {
    if (edge[i].t > lim) {
      AddEdge((ori + i) << 1 | 1, (ori + i) << 1 | 0);
    }
  }
  Solve();
  vector<int> ans;
  for (int i = 0; i < m / 2; ++i) {
    if (sccid[(ori + i) << 1 | 0] > sccid[(ori + i) << 1 | 1]) {
      ans.push_back(i);
    }
  }
  printf("%d %d\n", low, (int)ans.size());
  for (int i = 0; i < ans.size(); ++i) {
    printf("%d%c", ans[i] + 1, " \n"[i + 1 == ans.size()]);
  }
  return 0;
}
