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;
long long read() {
  long long x = 0, f = 0;
  char ch = getchar();
  while (!isdigit(ch)) f = ch == '-', ch = getchar();
  while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
  return f ? -x : x;
}
const int N = 50005 * 2 * 5;
int n, m, k;
vector<int> id[N], e[N], e2[N];
struct Edge {
  int x, y, c, t, id;
} E[N];
bool cmpt(Edge a, Edge b) { return a.t < b.t; }
bool cmpc(int a, int b) { return E[a].c < E[b].c; }
int op(int x) { return x <= m * 5 ? x + m * 5 : x - m * 5; }
int dfn[N], low[N], inst[N], st[N], bh[N], Time = 0, top = 0, scc = 0;
void Tarjan(int x) {
  dfn[x] = low[x] = ++Time;
  st[++top] = x;
  inst[x] = 1;
  for (auto y : e[x])
    if (!dfn[y]) {
      Tarjan(y);
      low[x] = min(low[x], low[y]);
    } else if (inst[y])
      low[x] = min(low[x], low[y]);
  if (low[x] == dfn[x]) {
    inst[st[top]] = 0;
    bh[st[top]] = ++scc;
    while (st[top--] != x) {
      inst[st[top]] = 0;
      bh[st[top]] = scc;
    }
  }
}
void AddEdge(int x, int y) {
  e[x].push_back(y);
  e[op(y)].push_back(op(x));
}
int o[N];
int vis[N];
void dfs(int x) {
  if (vis[x]) return;
  vis[x] = 1;
  for (auto y : e2[x]) dfs(y);
}
int check(int t) {
  memset(vis, 0, sizeof vis);
  for (int i = (t + 1); i <= (m); i++) dfs(bh[i]);
  queue<int> q;
  static int in[N];
  memset(in, 0, sizeof in);
  for (int i = (1); i <= (scc); i++)
    for (auto j : e2[i]) in[j]++;
  for (int i = (1); i <= (scc); i++)
    if (!in[i]) q.push(i);
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    if (!vis[x] && !vis[o[x]]) vis[x] = 1;
    for (auto y : e2[x])
      if (!--in[y]) q.push(y);
  }
  for (int i = (1); i <= (scc); i++)
    if (1 ^ vis[i] ^ vis[o[i]]) return 0;
  return 1;
}
int main() {
  n = read(), m = read();
  for (int i = (1); i <= (m); i++)
    E[i].x = read(), E[i].y = read(), E[i].c = read(), E[i].t = read(),
    E[i].id = i;
  sort(E + 1, E + m + 1, cmpt);
  for (int i = (1); i <= (m); i++) {
    int x = E[i].x, y = E[i].y;
    id[x].push_back(i), id[y].push_back(i);
  }
  k = m + 1;
  for (int i = (1); i <= (n); i++) {
    sort(id[i].begin(), id[i].end(), cmpc);
    int cnt = 0, x = 0, y = 0;
    for (int j = (1); j <= ((int)id[i].size() - 1); j++)
      if (E[id[i][j]].c == E[id[i][j - 1]].c)
        cnt++, x = id[i][j], y = id[i][j - 1];
    if (cnt > 1) return puts("No"), 0;
    if (cnt == 1) {
      AddEdge(x, op(y));
      AddEdge(op(x), y);
    }
    int t = (int)id[i].size();
    for (int j = (0); j <= ((int)id[i].size() - 1); j++) {
      AddEdge(id[i][j], k + j);
      AddEdge(id[i][j], k + j + t);
    }
    for (int j = (0); j <= ((int)id[i].size() - 2); j++) {
      AddEdge(k + j, k + j + 1);
      AddEdge(k + t + j + 1, k + t + j);
      AddEdge(k + j, op(k + j + t + 1));
    }
    k += t * 2;
  }
  k--;
  assert(k == m * 5);
  for (int i = (1); i <= (m * 10); i++)
    if (!dfn[i]) Tarjan(i);
  for (int i = (1); i <= (m * 10); i++)
    if (bh[i] == bh[op(i)]) return puts("No"), 0;
  for (int x = (1); x <= (m * 10); x++)
    for (auto y : e[x])
      if (bh[x] != bh[y]) e2[bh[y]].push_back(bh[x]);
  for (int i = (1); i <= (m * 10); i++) o[bh[i]] = bh[op(i)];
  int L = 0, R = m, ans = m + 1;
  while (L <= R) {
    int mid = (L + R) >> 1;
    if (check(mid))
      R = mid - 1, ans = mid;
    else
      L = mid + 1;
  }
  if (ans == m + 1) return (void)puts("No"), 0;
  check(ans);
  puts("Yes");
  vector<int> res;
  for (int i = (1); i <= (m); i++)
    if (vis[bh[op(i)]]) res.push_back(i);
  printf("%d %d\n", E[ans].t, (int)res.size());
  for (auto i : res) printf("%d ", E[i].id);
  puts("");
  return 0;
}
