#include <bits/stdc++.h>
using namespace std;
inline int Read() {
  char c = getchar();
  int num = 0;
  while ('0' > c || c > '9') c = getchar();
  while ('0' <= c && c <= '9') num = num * 10 + c - '0', c = getchar();
  return (num);
}
vector<int> c[1500010], E[1500010];
struct Edge {
  int to, old;
} e[2 * 1500010];
int l[1500010], df[1500010], le[1500010], st, q[1500010], top, tim,
    ins[1500010], lw[1500010], cnt, bl[1500010];
inline void Tarjan(int x) {
  df[x] = lw[x] = ++tim;
  ins[x] = 1, q[++top] = x;
  for (int i = l[x]; i; i = e[i].old)
    if (!df[e[i].to])
      Tarjan(e[i].to), lw[x] = min(lw[x], lw[e[i].to]);
    else if (ins[e[i].to])
      lw[x] = min(lw[x], df[e[i].to]);
  if (df[x] == lw[x]) {
    cnt++;
    for (int nw = -1; nw != x;)
      nw = q[top], q[top--] = 0, ins[nw] = 0, c[cnt].push_back(nw),
      bl[nw] = cnt;
  }
}
int N, tot, n, m;
vector<int> p[1500010];
struct Road {
  int u, v, t, c;
} a[1500010];
inline void Lnk(int x, int y) {
  e[++tot].to = y, e[tot].old = l[x], l[x] = tot;
}
inline void Prepare() {
  N = m * 2;
  for (int i = 1; i <= n; i++)
    for (int j = 0, k = 0; j < p[i].size(); j = k) {
      for (k = j; k < p[i].size() && a[p[i][k]].c == a[p[i][j]].c; k++)
        ;
      int n_ = N;
      for (int l = j; l < k; l++) Lnk(++N, 2 * p[i][l]);
      for (int l = n_ + 2; l <= N; l++) Lnk(l, l - 1);
      int n__ = N;
      for (int l = j; l < k; l++) Lnk(++N, 2 * p[i][l]);
      for (int l = n__ + 2; l <= N; l++) Lnk(l - 1, l);
      for (int l = j; l < k; l++) {
        if (l != j) Lnk(2 * p[i][l] - 1, n_ + l - j);
        if (l != k - 1) Lnk(2 * p[i][l] - 1, n__ + l - j + 2);
      }
    }
  for (int i = 1; i <= n; i++) {
    int n_ = N;
    for (int j = 0; j < p[i].size(); j++) Lnk(++N, 2 * p[i][j] - 1);
    for (int j = n_ + 2; j <= N; j++) Lnk(j, j - 1);
    int n__ = N;
    for (int j = 0; j < p[i].size(); j++) Lnk(++N, 2 * p[i][j] - 1);
    for (int j = n__ + 2; j <= N; j++) Lnk(j - 1, j);
    for (int j = 0; j < p[i].size(); j++) {
      if (j != 0) Lnk(2 * p[i][j], n_ + j);
      if (j != p[i].size() - 1) Lnk(2 * p[i][j], n__ + j + 2);
    }
  }
}
inline bool Check(int Mid, int cl) {
  int N_ = N, t_ = tot, ck = 1;
  N++;
  for (int i = 1; i <= m; i++)
    if (a[i].t > Mid) Lnk(N, i * 2 - 1);
  for (int i = 1; i <= m; i++) Lnk(i * 2, N), Lnk(i * 2 - 1, N);
  tim = cnt = 0;
  memset(df, 0, sizeof(df));
  for (int i = 1; i <= m * 2; i++)
    if (!df[i]) Tarjan(i);
  for (int i = 1; i <= m; i++)
    if (bl[i * 2] == bl[i * 2 - 1]) ck = 0;
  if (cl) {
    for (int i = 1; i <= cnt; i++) c[i].clear();
    for (int i = 1; i <= m * 2; i++)
      while (l[i] > t_) l[i] = e[l[i]].old;
    l[N--] = 0, tot = t_;
  }
  return (ck);
}
int cl[1500010], ans = -1, nc, d[1500010];
bool Cmpc(int x, int y) { return (a[x].c < a[y].c); }
int main() {
  int L = 0, R = 0;
  n = Read(), m = Read();
  for (int i = 1; i <= m; i++) {
    a[i].u = Read(), a[i].v = Read(), a[i].c = Read(), a[i].t = Read();
    p[a[i].u].push_back(i), p[a[i].v].push_back(i), R = max(R, a[i].t);
  }
  for (int i; i <= n; i++) sort(p[i].begin(), p[i].end(), Cmpc);
  Prepare();
  while (L <= R) {
    int Mid = (L + R) / 2;
    if (Check(Mid, 1))
      ans = Mid, R = Mid - 1;
    else
      L = Mid + 1;
  }
  if (ans == -1) {
    puts("No");
    return (0);
  }
  puts("Yes"), Check(ans, 0);
  int h = 0, t = 0;
  for (int i = 1; i <= N; i++)
    for (int j = l[i]; j; j = e[j].old)
      if (bl[i] != bl[e[j].to])
        E[bl[i]].push_back(bl[e[j].to]), d[bl[e[j].to]]++;
  for (int i = 1; i <= cnt; i++)
    if (!d[i]) q[++t] = i;
  while (h <= t) {
    int nw = q[h];
    for (int i = 0; i < c[nw].size(); i++) {
      int u = c[nw][i];
      if (u > m * 2) continue;
      if (!cl[(u + 1) / 2]) cl[(u + 1) / 2] = 2 - (u & 1);
    }
    for (int i = 0; i < E[nw].size(); i++) {
      d[E[nw][i]]--;
      if (!d[E[nw][i]]) q[++t] = E[nw][i];
    }
    h++;
  }
  for (int i = 1; i <= m; i++)
    if (cl[i] == 1) nc++;
  printf("%d %d\n", ans, nc);
  for (int i = 1; i <= m; i++)
    if (cl[i] == 1) printf("%d ", i);
}
