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 INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 5, MAXM = 5e4 + 5;
template <typename _T>
void read(_T &x) {
  x = 0;
  char s = getchar();
  int f = 1;
  while (s > '9' || s < '0') {
    if (s == '-') f = -1;
    s = getchar();
  }
  while (s >= '0' && s <= '9') {
    x = (x << 3) + (x << 1) + (s - '0'), s = getchar();
  }
  x *= f;
}
template <typename _T>
void write(_T x) {
  if (x < 0) {
    putchar('-');
    x = (~x) + 1;
  }
  if (9 < x) {
    write(x / 10);
  }
  putchar(x % 10 + '0');
}
template <typename _T>
_T MAX(const _T a, const _T b) {
  return a > b ? a : b;
}
template <typename _T>
_T MIN(const _T a, const _T b) {
  return a < b ? a : b;
}
vector<int> Graph[MAXN], G[MAXN], same;
int sta[MAXN], top;
int DFN[MAXN], LOW[MAXN], bel[MAXN];
int c[MAXM], t[MAXM];
int N, M, tot, ID, siz;
bool inSta[MAXN];
bool cmp(const int x, const int y) { return c[x] < c[y]; }
void addEdge(const int from, const int to) { Graph[from].push_back(to); }
void Tarjan(const int u) {
  DFN[u] = LOW[u] = ++ID;
  sta[++top] = u, inSta[u] = true;
  for (int i = 0, v; i < Graph[u].size(); i++) {
    if (!DFN[v = Graph[u][i]])
      Tarjan(v), LOW[u] = MIN(LOW[u], LOW[v]);
    else if (inSta[v])
      LOW[u] = MIN(LOW[u], DFN[v]);
  }
  if (DFN[u] == LOW[u]) {
    int v;
    ++tot;
    do {
      v = sta[top--];
      inSta[v] = false, bel[v] = tot;
    } while (v ^ u);
  }
}
void addE1(vector<int> Gr) {
  int nxt = Gr.size(), lst1, lst2;
  for (int i = 0; i < nxt; i++) {
    int x = Gr[i], y = Gr[i] + M, s = ++siz, t = ++siz;
    addEdge(x, s), addEdge(t, y);
    if (i)
      addEdge(lst1, s), addEdge(t, lst2), addEdge(lst1, y), addEdge(x, lst2);
    lst1 = s, lst2 = y;
  }
}
void addE2(vector<int> Gr) {
  int nxt = Gr.size(), lst1, lst2;
  for (int i = 0; i < nxt; i++) {
    int x = Gr[i], y = Gr[i] + M, s = ++siz, t = ++siz;
    addEdge(s, x), addEdge(y, t);
    if (i)
      addEdge(s, lst1), addEdge(lst2, t), addEdge(y, lst1), addEdge(lst2, x);
    lst1 = s, lst2 = y;
  }
}
void remove(const int len) {
  for (int i = 1; i <= M; i++)
    if (t[i] > len) Graph[i].pop_back();
}
bool chk(const int len) {
  top = tot = ID = 0;
  for (int i = 1; i <= siz; i++) DFN[i] = LOW[i] = bel[i] = inSta[i] = 0;
  for (int i = 1; i <= M; i++)
    if (t[i] > len) addEdge(i, i + M);
  for (int i = 1; i <= siz; i++)
    if (!DFN[i]) Tarjan(i);
  for (int i = 1; i <= M; i++)
    if (bel[i] == bel[i + M]) {
      remove(len);
      return false;
    }
  remove(len);
  return true;
}
int main() {
  int l = 0, r = -INF, mid;
  read(N), read(M);
  for (int i = 1, a, b; i <= M; i++)
    read(a), read(b), read(c[i]), read(t[i]), G[a].push_back(i),
        G[b].push_back(i), r = MAX(r, t[i]);
  siz = M << 1;
  for (int i = 1; i <= N; i++) {
    addE1(G[i]);
    std ::sort(G[i].begin(), G[i].end(), cmp);
    for (int k = 0, r; k < G[i].size(); k = r) {
      for (r = k; r < G[i].size() && c[G[i][r]] == c[G[i][k]];
           same.push_back(G[i][r++]))
        ;
      addE2(same), same.clear();
    }
  }
  if (!chk(INF)) {
    puts("No");
    return 0;
  }
  puts("Yes");
  while (l < r) {
    if (chk(mid = l + r >> 1))
      r = mid;
    else
      l = mid + 1;
  }
  chk(l);
  write(l), putchar(' ');
  int count = 0;
  for (int i = 1; i <= M; i++) count += bel[i] < bel[i + M];
  write(count), putchar('\n');
  for (int i = 1; i <= M; i++)
    if (bel[i] < bel[i + M]) write(i), putchar(' ');
  puts("");
  return 0;
}
