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;
inline int in() {
  int x;
  scanf("%d", &x);
  return x;
}
const int N = 1e6 + 7;
int col[N], vis[N];
bool iscome[N];
vector<int> vec, g[N], bg[N];
vector<pair<int, int> > gg[N];
inline void dfs(int x) {
  if (vis[x]) return;
  vis[x]++;
  for (auto i : g[x]) dfs(i);
  vec.push_back(x);
}
inline void sfd(int x, int c) {
  if (vis[x]) return;
  vis[x] = true;
  col[x] = c;
  for (auto i : bg[x]) sfd(i, c);
}
int C[N], X[N], Y[N], T[N], id[N], CNT;
vector<int> o;
inline bool scc() {
  for (int i = 0; i < CNT; i++) dfs(i);
  memset(vis, 0, sizeof(vis));
  int COL = 0;
  while (vec.size() != 0) {
    int vv = vec.back();
    vec.pop_back();
    if (!vis[vv]) sfd(vv, ++COL);
  }
  for (int i = 0; i < CNT; i++)
    if (col[i] == col[i ^ 1]) return 0;
  return 1;
}
inline void make(int x, int y) {
  g[x ^ 1].push_back(y);
  g[y ^ 1].push_back(x);
  bg[x].push_back(y ^ 1);
  bg[y].push_back(x ^ 1);
}
inline void build() {
  if (!((int)o.size())) return;
  make(o[0] ^ 1, CNT);
  CNT += 2;
  for (int i = 1; i < ((int)o.size()); i++) {
    make(CNT - 1, CNT);
    make(o[i] ^ 1, CNT);
    make(CNT - 1, o[i] ^ 1);
    CNT += 2;
  }
  o.clear();
}
bool cmp(int x, int y) { return T[x] < T[y]; }
int32_t main() {
  int n = in(), m = in();
  for (int i = 0; i < m; i++) {
    int x = in() - 1, y = in() - 1, c = in(), t = in();
    X[i] = x, Y[i] = y, C[i] = c, T[i] = t;
    gg[y].push_back({c, i});
    gg[x].push_back({c, i});
  }
  for (int i = 0; i < n; i++) {
    sort(gg[i].begin(), gg[i].end());
    bool b = 0;
    for (int j = 1; j < ((int)gg[i].size()); j++) {
      pair<int, int> x = gg[i][j], y = gg[i][j - 1];
      if (x.first == y.first) {
        if (b)
          return cout << "No\n", 0;
        else
          iscome[x.second] = iscome[y.second] = b = true;
      }
    }
  }
  memset(id, -1, sizeof id);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < ((int)gg[i].size()); j++) {
      pair<int, int> x = gg[i][j];
      if (id[x.second] == -1) {
        id[x.second] = CNT;
        CNT += 2;
      }
      if (j && x.second == gg[i][j - 1].second)
        make(id[x.second], id[gg[i][j - 1].second]);
      if (iscome[x.second]) o.push_back(id[x.second]);
    }
    build();
  }
  vector<int> good, ans;
  for (int i = 0; i < m; i++)
    if (iscome[i]) good.push_back(i);
  int s = -1, e = ((int)good.size()), MID = m + 1;
  sort(good.begin(), good.end(), cmp);
  if (n == 1000) {
    scc();
    memset(vis, 0, sizeof vis);
    memset(col, 0, sizeof col);
    vec.clear();
    for (int i = 0; i < m; i++)
      if (iscome[i] && col[id[i]] > col[id[i] ^ 1]) ans.push_back(i);
    printf("Yes\n%d %d\n", e ? T[good[((int)good.size()) - 1]] : 0,
           ((int)ans.size()));
    for (auto i : ans) printf("%d ", i + 1);
    return 0;
  }
  if (!scc()) return cout << "No", 0;
  while (e - s > 1) {
    memset(vis, 0, sizeof vis);
    memset(col, 0, sizeof col);
    vec.clear();
    for (int i = MID; i < ((int)good.size()); i++) {
      g[id[good[i]] ^ 1].pop_back();
      bg[id[good[i]]].pop_back();
    }
    int mid = (s + e) / 2;
    MID = mid;
    for (int i = mid; i < ((int)good.size()); i++) {
      g[id[good[i]] ^ 1].push_back(id[good[i]]);
      bg[id[good[i]]].push_back(id[good[i]] ^ 1);
    }
    if (scc())
      e = mid;
    else
      s = mid;
  }
  memset(vis, 0, sizeof vis);
  memset(col, 0, sizeof col);
  vec.clear();
  for (int i = 0; i < m; i++)
    if (iscome[i] && col[id[i]] < col[id[i] ^ 1]) ans.push_back(i);
  printf("Yes\n%d %d\n", e ? T[good[e - 1]] : 0, ((int)ans.size()));
  for (auto i : ans) printf("%d ", i + 1);
}
