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;
struct data {
  int n, c, t, i;
  data(int _n, int _c, int _t, int _i) : n(_n), c(_c), t(_t), i(_i) {}
};
const int maxn = 50010;
int n, m;
vector<data> adj[maxn];
vector<int> vadj[4 * maxn], tadj[4 * maxn];
int indeg[4 * maxn];
int num;
bool cmp(data d1, data d2) { return d1.c < d2.c; }
void add(int a, int b) { vadj[a].push_back(b); }
void add2(int a, int b) {
  add((a + 2 * maxn) % (4 * maxn), b);
  add((b + 2 * maxn) % (4 * maxn), a);
}
void go(vector<int> v) {
  while (v.size() > 1) {
    vector<int> w;
    int s = v.size();
    for (int i = 0; i < s / 2; i++) {
      add2(v[2 * i] + 2 * maxn, v[2 * i + 1] + 2 * maxn);
      add2(v[2 * i] + 2 * maxn, num);
      add2(v[2 * i + 1] + 2 * maxn, num);
      w.push_back(num);
      num++;
      if (num >= 2 * maxn) exit(0);
    }
    if (s & 1) w.push_back(v[s - 1]);
    v = w;
  }
}
bool in[4 * maxn];
int ind[4 * maxn], lowlink[4 * maxn], cnt;
int stk[4 * maxn], stksze;
int par[4 * maxn];
int getpar(int a) { return par[a] == a ? a : par[a] = getpar(par[a]); }
void merge(int a, int b) { par[getpar(a)] = getpar(b); }
void dfs(int cur) {
  ind[cur] = lowlink[cur] = cnt++;
  stk[stksze++] = cur, in[cur] = 1;
  for (int i : vadj[cur]) {
    if (ind[i] == -1) {
      dfs(i);
      lowlink[cur] = min(lowlink[cur], lowlink[i]);
    } else if (in[i])
      lowlink[cur] = min(lowlink[cur], ind[i]);
  }
  if (ind[cur] == lowlink[cur]) {
    while (stk[stksze - 1] != cur) {
      merge(stk[stksze - 1], cur);
      in[stk[stksze - 1]] = 0;
      stksze--;
    }
    assert(stk[stksze - 1] == cur);
    in[cur] = 0;
    stksze--;
  }
}
int ord[4 * maxn], ocnt;
void dfs2(int cur) {
  ord[cur] = ocnt++;
  for (int i : tadj[cur]) {
    indeg[i]--;
    if (!indeg[i]) dfs2(i);
  }
}
int ans[maxn], sans;
bool check(int mt, bool pans = 0) {
  for (int i = 0; i < 4 * maxn; i++) vadj[i].clear();
  num = m;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < adj[i].size(); j++) {
      data d = adj[i][j];
      if (d.t > mt) add(d.i, d.i + 2 * maxn);
      if (j && adj[i][j].c == adj[i][j - 1].c) {
        add2(d.i, adj[i][j - 1].i);
      }
    }
    vector<int> v;
    for (data d : adj[i]) v.push_back(d.i);
    go(v);
  }
  for (int i = 0; i < 4 * maxn; i++) par[i] = i, ind[i] = -1;
  for (int i = 0; i < 4 * maxn; i++)
    if (ind[i] == -1) dfs(i);
  for (int i = 0; i < 2 * maxn; i++)
    if (getpar(i) == getpar(i + 2 * maxn)) {
      return 0;
    }
  if (pans) {
    memset(indeg, 0, sizeof(indeg));
    for (int i = 0; i < 4 * maxn; i++) {
      int x = getpar(i);
      for (int j : vadj[i])
        if (x != getpar(j)) {
          tadj[x].push_back(getpar(j));
          indeg[getpar(j)]++;
        }
    }
    memset(ord, -1, sizeof(ord));
    for (int i = 0; i < 4 * maxn; i++)
      if (!indeg[i] && ord[i] == -1) dfs2(i);
    for (int i = 0; i < m; i++) {
      if (ord[getpar(i)] > ord[getpar(i + 2 * maxn)]) ans[sans++] = i + 1;
    }
  }
  return 1;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int a, b, c, t;
    cin >> a >> b >> c >> t;
    a--, b--;
    adj[a].push_back(data(b, c, t, i));
    adj[b].push_back(data(a, c, t, i));
  }
  for (int i = 0; i < n; i++) {
    sort(adj[i].begin(), adj[i].end(), cmp);
    int num = 0;
    for (int j = 0; j < adj[i].size(); j++)
      if (j && adj[i][j].c == adj[i][j - 1].c) num++;
    if (num > 1) {
      cout << "No\n";
      return 0;
    }
  }
  int lo = 0, hi = 1e9 + 5;
  while (lo < hi) {
    int mid = (lo + hi) / 2;
    if (check(mid))
      hi = mid;
    else
      lo = mid + 1;
  }
  if (lo == 1e9 + 5)
    cout << "No\n";
  else {
    cout << "Yes\n";
    check(lo, 1);
    cout << lo << ' ' << sans << '\n';
    for (int i = 0; i < sans; i++) cout << ans[i] << ' ';
    cout << '\n';
  }
}
