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>
#pragma GCC optimize("O2")
using namespace std;
const int N = 4e5 + 10;
const long long mod = 1e9 + 7;
const long long mod2 = 998244353;
const long long inf = 8e18;
const int LOG = 22;
long long pw(long long a, long long b, long long M) {
  return (!b ? 1
             : (b & 1 ? (a * pw(a * a % M, b / 2, M)) % M
                      : pw(a * a % M, b / 2, M)));
}
int n, m, ptr, T[N], C[N], mark[N], Ans[N];
vector<int> adj[N], adt[N], G[N], pre[N], suf[N], top;
inline void add(int v, int u) {
  adj[v].push_back(u);
  adt[u].push_back(v);
}
bool cmp(int v, int u) { return C[v] < C[u]; }
void dfs(int v) {
  mark[v] = 1;
  for (auto u : adj[v]) {
    if (mark[u]) continue;
    dfs(u);
  }
  top.push_back(v);
}
void sfd(int v) {
  for (auto u : adt[v]) {
    if (mark[u]) continue;
    mark[u] = mark[v];
    sfd(u);
  }
}
bool check(int x) {
  memset(Ans, 0, sizeof Ans);
  memset(mark, 0, sizeof mark);
  top.clear();
  for (int i = 1; i <= m; i++) {
    if (T[i] > x) {
      add(i << 1, i << 1 | 1);
    }
  }
  memset(mark, 0, sizeof mark);
  for (int i = 2; i <= ((ptr << 1) | 1); i++) {
    if (!mark[i]) dfs(i);
  }
  reverse((top).begin(), (top).end());
  int col = 0, is_ok = 1;
  memset(mark, 0, sizeof mark);
  for (auto v : top) {
    if (!mark[v]) {
      mark[v] = ++col;
      sfd(v);
    }
  }
  for (int i = 1; i <= ptr; i++) {
    if (mark[i << 1] == mark[i << 1 | 1]) is_ok = 0;
    Ans[i] = (mark[i << 1] > mark[i << 1 | 1]);
  }
  for (int i = 1; i <= m; i++) {
    if (T[i] > x) {
      adj[i << 1].pop_back();
      adt[i << 1 | 1].pop_back();
    }
  }
  return is_ok;
}
int main() {
  scanf("%d%d", &n, &m);
  ptr = m;
  for (int i = 1; i <= m; i++) {
    int a, b;
    scanf("%d%d%d%d", &a, &b, &C[i], &T[i]);
    G[a].push_back(i);
    G[b].push_back(i);
  }
  for (int i = 1; i <= n; i++) {
    sort((G[i]).begin(), (G[i]).end(), cmp);
    int sz = (int)G[i].size();
    if (sz == 0) continue;
    for (int j = 0; j < sz; j++) {
      ptr++, pre[i].push_back(ptr);
      add(ptr << 1, G[i][j] << 1 | 1);
      if (j) {
        add(ptr << 1, pre[i][j - 1] << 1);
      }
    }
    suf[i].resize(sz, 0);
    for (int j = sz - 1; ~j; j--) {
      suf[i][j] = ++ptr;
      add(ptr << 1, G[i][j] << 1 | 1);
      if (j < sz - 1) {
        add(suf[i][j] << 1, suf[i][j + 1] << 1);
      }
    }
    int same = 0;
    for (int j = 0; j < sz; j++) {
      int a = G[i][j];
      if (j && C[G[i][j]] == C[G[i][j - 1]]) {
        if (same) return !printf("No");
        same = 1;
        int b = G[i][j - 1];
        add(a << 1, b << 1 | 1);
        add(a << 1 | 1, b << 1);
        add(b << 1, a << 1 | 1);
        add(b << 1 | 1, a << 1);
      }
      if (j) {
        add(a << 1, pre[i][j - 1] << 1);
      }
      if (j != sz - 1) {
        add(a << 1, suf[i][j + 1] << 1);
      }
    }
  }
  if (check(1e9 + 10) == 0) return !printf("No");
  int d = 0, up = 1e9 + 10;
  while (up - d > 1) {
    int mid = (up + d) >> 1;
    if (check(mid)) {
      up = mid;
    } else {
      d = mid;
    }
  }
  check(up);
  printf("Yes\n");
  vector<int> tot;
  for (int i = 1; i <= m; i++) {
    if (Ans[i]) tot.push_back(i);
  }
  printf("%d %d\n", up, (int)tot.size());
  for (auto x : tot) printf("%d ", x);
  return 0;
}
