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>
uint32_t readu32() {
  int c;
  while ((c = getchar_unlocked()) < '0')
    ;
  uint32_t n = c & 15U;
  while ((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U);
  return n;
}
uint64_t readu64() {
  int c;
  while ((c = getchar_unlocked()) < '0')
    ;
  uint64_t n = c & 15U;
  while ((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U);
  return n;
}
int32_t read32() {
  int c;
  while ((c = getchar_unlocked()) < '-')
    ;
  bool neg = c == '-';
  if (neg) c = getchar_unlocked();
  uint32_t n = c & 15U;
  while ((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U);
  return neg ? -(int32_t)n : n;
}
int64_t read64() {
  int c;
  while ((c = getchar_unlocked()) < '-')
    ;
  bool neg = c == '-';
  if (neg) c = getchar_unlocked();
  uint64_t n = c & 15;
  while ((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U);
  return neg ? -(int64_t)n : n;
}
using namespace std;
void No() {
  cout << "No";
  exit(0);
}
struct rd {
  int u, v, c, t;
};
struct pr {
  int r1, r2;
};
vector<int> aj[50001];
rd r[50001];
int rj[50001][2];
bool rv[50001];
int ro_[2][50001];
int* ro[] = {ro_[0], ro_[1]};
int main() {
  ios_base::sync_with_stdio(0);
  int n = (readu32()), m = (readu32());
  for (int i = 0; i++ < m;) {
    aj[r[i].u = (readu32())].push_back(i);
    aj[r[i].v = (readu32())].push_back(i);
    r[i].c = (readu32());
    r[i].t = (readu32());
  }
  for (int i = 0; i++ < n;) {
    map<int, int> cols;
    bool dup = false;
    for (int j = 0; j < aj[i].size(); j++) {
      auto ins = cols.insert({r[aj[i][j]].c, aj[i][j]});
      if (!ins.second) {
        if (dup) No();
        dup = true;
        int a = ins.first->second, b = aj[i][j];
        rj[a][!!rj[a][0]] = b;
        rj[b][!!rj[b][0]] = a;
      }
    }
  }
  int tot = 0;
  bool p1 = true;
ll:
  for (int i = 0; i++ < m;) {
    if (!rj[i][0] || rv[i] || (p1 && rj[i][1])) continue;
    int cur = i;
    int c[2]{};
    int l = 0, pre = 0;
    for (;;) {
      rv[cur] = 1;
      c[l & 1] = max(c[l & 1], r[cur].t);
      *ro[l & 1]++ = cur;
      l++;
      if (l > 1 && !rj[cur][1]) break;
      int cur0 = cur;
      cur = rj[cur][rj[cur][0] == pre];
      if (cur == i) break;
      pre = cur0;
    }
    if (!p1 && l & 1) No();
    int u = c[1] < c[0];
    tot = max(tot, c[u]);
    ro[!u] -= l + u >> 1;
  }
  if (p1) {
    p1 = false;
    goto ll;
  }
  cout << "Yes\n" << tot << ' ' << (ro[0] - ro_[0]) + (ro[1] - ro_[1]) << '\n';
  for (int i : {0, 1})
    while (ro[i] > ro_[i]) cout << *--ro[i] << ' ';
  return 0;
}
