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>
template <class T1, class T2>
inline bool cmin(T1 &a, const T2 &b) {
  return b < a ? (a = b, true) : false;
}
template <class T1, class T2>
inline bool cmax(T1 &a, const T2 &b) {
  return a < b ? (a = b, true) : false;
}
template <class Type>
Type read() {
  Type a;
  bool b;
  unsigned char c;
  while (c = getchar() - 48, (c > 9) & (c != 253))
    ;
  for (a = (b = c == 253) ? 0 : c; (c = getchar() - 48) <= 9; a = a * 10 + c)
    ;
  return b ? -a : a;
}
int (*rd)() = read<int>;
const int N = 5e4 + 1;
int n, m, tot, to[2 * N], c[N], t[N], real[N], pre[2 * N], last[N];
int dfs_n, dfn[4 * N], low[4 * N], stack[4 * N], *top = stack, out_n,
                                                 out[4 * N];
std::vector<int> e[N], edge[4 * N];
void dfs(int u) {
  dfn[u] = low[u] = ++dfs_n;
  *top++ = u;
  for (int v : edge[u]) {
    if (!dfn[v]) {
      dfs(v);
      cmin(low[u], low[v]);
    } else if (!out[v])
      cmin(low[u], dfn[v]);
  }
  if (dfn[u] == low[u]) {
    int v;
    ++out_n;
    do {
      v = *--top;
      out[v] = out_n;
    } while (v != u);
  }
}
bool check(int lim) {
  for (int i = 1; i <= 4 * m; ++i) edge[i].clear();
  for (int i = 1, j; i <= m; ++i) {
    if (t[i] > lim) edge[m + i].push_back(i);
    if ((j = pre[2 * i])) {
      edge[i].push_back(m + j);
      edge[j].push_back(m + i);
    }
    if ((j = pre[2 * i + 1])) {
      edge[i].push_back(m + j);
      edge[j].push_back(m + i);
    }
  }
  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j < e[i].size(); ++j) {
      edge[2 * m + e[i][j - 1] / 2].push_back(2 * m + e[i][j] / 2);
      edge[3 * m + e[i][j] / 2].push_back(3 * m + e[i][j - 1] / 2);
      edge[m + e[i][j - 1] / 2].push_back(2 * m + e[i][j] / 2);
      edge[m + e[i][j] / 2].push_back(3 * m + e[i][j - 1] / 2);
    }
    for (int j = 0; j < e[i].size(); ++j) {
      edge[2 * m + e[i][j] / 2].push_back(e[i][j] / 2);
      edge[3 * m + e[i][j] / 2].push_back(e[i][j] / 2);
    }
  }
  dfs_n = out_n = 0;
  memset(dfn + 1, 0, 4 * m * sizeof(int));
  memset(out + 1, 0, 4 * m * sizeof(int));
  for (int i = 1; i <= 4 * m; ++i)
    if (!dfn[i]) dfs(i);
  for (int i = 1; i <= m; ++i)
    if (out[i] == out[m + i]) return false;
  return true;
}
int main() {
  n = rd(), m = rd();
  for (int i = 1; i <= m; ++i) {
    to[2 * i + 1] = rd(), to[2 * i] = rd(), c[i] = rd(), t[i] = rd();
    e[to[2 * i + 1]].push_back(2 * i);
    e[to[2 * i]].push_back(2 * i + 1);
  }
  std::copy(c + 1, c + m + 1, real);
  std::sort(real, real + m);
  tot = std::unique(real, real + m) - real;
  for (int i = 1; i <= m; ++i)
    c[i] = std::lower_bound(real, real + tot, c[i]) - real;
  std::copy(t + 1, t + m + 1, real);
  std::sort(real, real + m);
  tot = std::unique(real, real + m) - real;
  for (int i = 1; i <= m; ++i)
    t[i] = std::lower_bound(real, real + tot, t[i]) - real;
  for (int i = 1; i <= n; ++i) {
    for (int j : e[i]) {
      int col = c[j / 2];
      if (last[col] > 0) {
        pre[j] = last[col];
        last[col] = -1;
      } else if (last[col] == 0) {
        last[col] = j / 2;
      } else {
        puts("No");
        return 0;
      }
    }
    for (int j : e[i]) last[c[j / 2]] = 0;
  }
  int l = 0, r = tot;
  if (check(-1)) {
    puts("Yes\n0 0");
    return 0;
  }
  while (l != r) {
    int mid = (l + r) / 2;
    if (check(mid))
      r = mid;
    else
      l = mid + 1;
  }
  if (l == tot) {
    puts("No");
  } else {
    std::vector<int> ans;
    check(l);
    for (int i = 1; i <= m; ++i)
      if (out[i + m] < out[i]) ans.push_back(i);
    printf("Yes\n%d %d\n", real[l], (int)ans.size());
    for (int x : ans) printf("%d ", x);
    puts("");
  }
  return 0;
}
