#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 10;
int n, m, tot, u, v, c, x;
vector<int> vc[maxn], temp, g[maxn], A;
struct node {
  int u, v, c, x;
} p[maxn];
bool cmp(int x, int y) { return p[x].c < p[y].c; }
void add_edge(int u, int v) { g[u].push_back(v); }
void go1() {
  int S, T;
  for (int i = 0; i < temp.size(); i++) {
    u = temp[i], v = temp[i] + m;
    int s = ++tot, t = ++tot;
    add_edge(u, s);
    add_edge(t, v);
    if (i) {
      add_edge(S, s), add_edge(t, T);
      add_edge(S, v), add_edge(u, T);
    }
    S = s, T = t;
  }
  temp.clear();
}
void go2() {
  int S, T;
  for (int i = 0; i < temp.size(); i++) {
    u = temp[i], v = temp[i] + m;
    int s = ++tot, t = ++tot;
    add_edge(s, u);
    add_edge(v, t);
    if (i) {
      add_edge(s, S), add_edge(T, t);
      add_edge(v, S), add_edge(T, u);
    }
    S = s, T = t;
  }
  temp.clear();
}
int color, id, Index;
int vis[maxn], dfn[maxn], stk[maxn], low[maxn], belong[maxn];
void tarjan(int now) {
  dfn[now] = low[now] = ++color;
  stk[++Index] = now;
  vis[now] = 1;
  for (auto to : g[now]) {
    if (!dfn[to]) {
      tarjan(to);
      low[now] = min(low[now], low[to]);
    } else if (vis[to])
      low[now] = min(low[now], dfn[to]);
  }
  if (low[now] == dfn[now]) {
    id++;
    while (1) {
      belong[stk[Index]] = id;
      vis[stk[Index]] = 0;
      Index--;
      if (now == stk[Index + 1]) break;
    }
  }
}
bool check(int o) {
  for (int i = 1; i <= m; i++)
    if (p[i].x > o) add_edge(i, i + m);
  for (int i = 1; i <= tot; i++) dfn[i] = 0, vis[i] = 0;
  color = id = Index = 0;
  for (int i = 1; i <= tot; i++)
    if (!dfn[i]) tarjan(i);
  for (int i = 1; i <= m; i++)
    if (p[i].x > o) g[i].pop_back();
  for (int i = 1; i <= m; i++)
    if (belong[i] == belong[i + m]) return 0;
  return 1;
}
int main() {
  scanf("%d %d", &n, &m);
  tot = m * 2;
  int st = 0, ed = 0;
  for (int i = 1; i <= m; i++) {
    scanf("%d %d %d %d", &u, &v, &c, &x);
    ed = max(ed, x);
    p[i] = {u, v, c, x};
    vc[u].push_back(i);
    vc[v].push_back(i);
  }
  for (int i = 1; i <= n; i++) {
    sort(vc[i].begin(), vc[i].end(), cmp);
    temp = vc[i];
    go1();
    for (int l = 0, r = 0; l < vc[i].size(); l = ++r) {
      temp.push_back(vc[i][l]);
      while (r + 1 < vc[i].size() && p[vc[i][r + 1]].c == p[vc[i][r]].c)
        temp.push_back(vc[i][++r]);
      go2();
    }
  }
  if (!check(ed)) return puts("No"), 0;
  puts("Yes");
  int ans = ed;
  while (st <= ed) {
    int mid = st + ed >> 1;
    if (check(mid)) {
      ans = mid;
      ed = mid - 1;
    } else
      st = mid + 1;
  }
  check(ans);
  for (int i = 1; i <= m; i++)
    if (belong[i] < belong[i + m]) A.push_back(i);
  printf("%d %d\n", ans, A.size());
  for (auto it : A) printf("%d ", it);
  return 0;
}
