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;
const int N = 200000 + 77;
struct SAT {
  int n, gp[N << 1], nt;
  bool M[N << 1], res[N << 1];
  vector<pair<bool, int> > a[N << 1];
  vector<int> ts;
  SAT(int n1) {
    n = n1;
    Clear();
  }
  void Clear() {
    ts.clear();
    nt = 0;
    for (int i = 0; i < (n << 1); i++) {
      M[i] = false;
      a[i].clear();
      gp[i] = 0;
      res[i] = false;
    }
  }
  void Add(int x, int y) {
    a[x ^ 1].push_back(make_pair(1, y));
    a[y].push_back(make_pair(0, x ^ 1));
    a[y ^ 1].push_back(make_pair(1, x));
    a[x].push_back(make_pair(0, y ^ 1));
  }
  bool Check() {
    for (int i = 2; i <= (n << 1) + 1; i++) M[i] = false;
    ts.clear();
    for (int i = 2; i <= (n << 1) + 1; i++) {
      if (!M[i]) {
        dfs(i);
      }
    }
    for (int i = 2; i <= (n << 1) + 1; i++) M[i] = false;
    while (ts.size()) {
      if (M[ts.back()]) {
        ts.pop_back();
        continue;
      }
      ++nt;
      findscc(ts.back());
      ts.pop_back();
    }
    for (int i = 2; i <= (n << 1) + 1; i++) {
      if (gp[i] == gp[i ^ 1]) return false;
    }
    return true;
  }
  void dfs(int v) {
    M[v] = true;
    for (auto x : a[v]) {
      int u = x.second;
      bool t = x.first;
      if ((!t) || (M[u])) continue;
      dfs(u);
    }
    ts.push_back(v);
  }
  void findscc(int v) {
    gp[v] = nt;
    M[v] = true;
    for (auto x : a[v]) {
      int u = x.second;
      bool t = x.first;
      if (t || M[u]) continue;
      findscc(u);
    }
  }
  vector<bool> GetAnswer() {
    for (int i = 2; i <= (n << 1) + 1; i++) M[i] = false;
    ts.clear();
    for (int i = 2; i <= (n << 1) + 1; i++) {
      if (!M[i]) {
        dfs(i);
      }
    }
    while (ts.size()) {
      int v = ts.back();
      res[v] = !res[v ^ 1];
      ts.pop_back();
    }
    vector<bool> r;
    for (int i = 2; i <= (n << 1); i += 2) {
      r.push_back(!res[i]);
    }
    return r;
  }
};
int n, m, Qv[N], Qu[N], Qt[N], Qc[N];
bool bad = 0;
vector<int> a[N], V, b[N];
map<int, int> M[N];
map<int, vector<int> > Mv[N];
bool Check(int x, bool print = 0) {
  SAT TST = SAT(N - 10);
  for (int i = 1; i <= m; i++) {
    if (Qt[i] > x) {
      TST.Add((i << 1) ^ 1, (i << 1) ^ 1);
    }
  }
  int more = 1e5;
  for (int i = 1; i <= n; i++) {
    if (!b[i].empty()) {
      int f = b[i][0], s = b[i][1];
      TST.Add((f << 1), (s << 1));
    }
    int sz = a[i].size();
    if (sz == 0) {
      continue;
    }
    for (int j = 0; j < sz; j++) {
      if (0 < j) {
        TST.Add((more + j - 1) << 1 ^ 1, (more + j) << 1);
      }
      TST.Add((a[i][j] << 1) ^ 1, ((more + j) << 1));
      if (j < sz - 1) {
        TST.Add(((more + j) << 1) ^ 1, ((a[i][j + 1] << 1) ^ 1));
      }
    }
    more += sz;
  }
  if (!print) {
    return TST.Check();
  }
  vector<bool> T = TST.GetAnswer();
  vector<int> A;
  for (int i = 0; i < m; i++) {
    if (T[i]) {
      A.push_back(i + 1);
    }
  }
  printf("%d %d\n", x, (int)A.size());
  for (auto z : A) {
    printf("%d ", z);
  }
  return 1;
}
int main() {
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= m; i++) {
    scanf("%d %d %d %d", &Qv[i], &Qu[i], &Qc[i], &Qt[i]);
    a[Qv[i]].push_back(i);
    a[Qu[i]].push_back(i);
    M[Qv[i]][Qc[i]]++;
    M[Qu[i]][Qc[i]]++;
    Mv[Qv[i]][Qc[i]].push_back(i);
    Mv[Qu[i]][Qc[i]].push_back(i);
    V.push_back(Qt[i]);
  }
  for (int i = 1; i <= n; i++) {
    int td = 0;
    for (auto x : M[i]) {
      if (x.second > 2) {
        bad = 1;
      }
      if (x.second == 2) {
        for (auto y : Mv[i][x.first]) {
          b[i].push_back(y);
        }
        td++;
      }
    }
    if (td > 1) {
      bad = 1;
    }
  }
  if (bad) {
    printf("No\n");
    return 0;
  }
  V.push_back(0);
  V.push_back(2e9);
  sort(V.begin(), V.end());
  V.resize(unique(V.begin(), V.end()) - V.begin());
  int le = -1, ri = (int)V.size() - 1;
  while (ri - le > 1) {
    int mid = (ri + le) / 2;
    if (Check(V[mid])) {
      ri = mid;
    } else {
      le = mid;
    }
  }
  if (V[ri] == 2e9) {
    printf("No\n");
    return 0;
  }
  printf("Yes\n");
  Check(V[ri], 1);
  return 0;
}
