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;
void PR(vector<int>& v) {
  for (auto& x : v) cout << x << ' ';
  cout << endl;
}
struct TwoSat {
  int N;
  vector<vector<int> > gr;
  vector<int> seen, values;
  TwoSat(int n = 0) : N(n), gr(2 * n) {}
  int add_var() {
    gr.emplace_back();
    gr.emplace_back();
    return N++;
  }
  void add_clause(int a_index, bool a_value, int b_index, bool b_value) {
    int a = 2 * a_index + a_value, b = 2 * b_index + b_value;
    gr[a ^ 1].push_back(b);
    gr[b ^ 1].push_back(a);
  }
  void set_value(int index, bool value) {
    add_clause(index, value, index, value);
  }
  void at_most_one(const vector<int>& li, bool val = 1) {
    if ((int)(li).size() <= 1) return;
    int cur = li[0];
    for (int i = 2; i < int((int)(li).size()); ++i) {
      int next = add_var();
      add_clause(cur, !val, li[i], !val);
      add_clause(cur, !val, next, val);
      add_clause(li[i], !val, next, val);
      cur = next;
    }
    add_clause(cur, !val, li[1], !val);
  }
  void dfs(int v) {
    if (seen[v]++) return;
    for (auto& e : gr[v]) dfs(e);
    if (values[v >> 1] == -1) values[v >> 1] = v & 1;
  }
  bool solve() {
    values.assign(N, -1);
    seen.assign(2 * N, 0);
    for (int i = 0; i < int(2 * N); ++i) dfs(i);
    for (int i = 0; i < int(N); ++i)
      for (int e : gr[i * 2 + values[i]])
        if (values[e >> 1] != (e & 1)) return 0;
    return 1;
  }
};
int main() {
  cin.sync_with_stdio(false);
  int N, M;
  cin >> N >> M;
  vector<vector<int> > ed(N);
  vector<map<int, vector<int> > > ced(N);
  vector<int> times;
  for (int i = 0; i < int(M); ++i) {
    int u, v, c, t;
    cin >> u >> v >> c >> t;
    --u, --v;
    times.push_back(t);
    ed[u].emplace_back(i);
    ed[v].emplace_back(i);
    ced[u][c].push_back(i);
    ced[v][c].push_back(i);
  }
  TwoSat* ts = 0;
  auto works = [&](int lim) {
    delete ts;
    ts = new TwoSat(M);
    for (int i = 0; i < int(M); ++i)
      if (times[i] > lim) ts->set_value(i, false);
    for (int i = 0; i < int(N); ++i) {
      ts->at_most_one(ed[i], 1);
      for (auto& pa : ced[i]) ts->at_most_one(pa.second, 0);
    }
    return ts->solve();
  };
  int hi = 1e9;
  if (!works(hi)) {
    cout << "No" << endl;
  } else {
    int lo = -1;
    while (lo + 1 < hi) {
      int mid = (hi + lo) / 2;
      if (works(mid))
        hi = mid;
      else
        lo = mid;
    }
    works(hi);
    cout << "Yes" << endl;
    cout << hi << ' ';
    vector<int> dest;
    for (int i = 0; i < int(M); ++i)
      if (ts->values[i]) dest.push_back(i + 1);
    cout << (int)(dest).size() << endl;
    PR(dest);
  }
}
