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>
inline int read() {
  char c = getchar();
  int x = 0, ft = 1;
  for (; c < '0' || c > '9'; c = getchar())
    if (c == '-') ft = -1;
  for (; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
  return x * ft;
}
inline int min(int a, int b) { return a < b ? a : b; }
inline void chkmax(int& a, int b) {
  if (a < b) a = b;
}
const int N = 1e5 + 5;
int n, m, val[N], t1[N], c1, t2[N], c2;
int h[N * 6], edge_cnt, dfn[N * 6], low[N * 6], dfs_clock;
int stk[N * 6], stp, ins[N * 6], sccno[N * 6], scc_cnt;
struct Edge {
  int to, nex;
} e[N * 20];
inline void add_edge(int u, int v) {
  e[++edge_cnt] = (Edge){v, h[u]};
  h[u] = edge_cnt;
}
struct Node {
  int c, v, id;
  bool operator<(const Node& r) const { return v < r.v; }
};
int s[N], node_cnt, tag[N];
std::vector<Node> edge[N], q[N];
std::vector<int> col, que;
inline void solve1(std::vector<Node> q) {
  int len = (int)q.size();
  if (len <= 1) return;
  for (int i = 0; i < len; ++i) s[i] = ++node_cnt;
  for (int i = 0; i < len; ++i) {
    add_edge((q[i].id << 1 | 1), (s[i] << 1 | 1));
    add_edge((s[i] << 1 | 0), (q[i].id << 1 | 0));
    if (i + 1 < len) {
      add_edge((s[i] << 1 | 1), (s[i + 1] << 1 | 1));
      add_edge((s[i + 1] << 1 | 0), (s[i] << 1 | 0));
      add_edge((s[i] << 1 | 1), (q[i + 1].id << 1 | 0));
      add_edge((q[i + 1].id << 1 | 1), (s[i] << 1 | 0));
    }
  }
}
inline void solve2(std::vector<Node> q) {
  int len = (int)q.size();
  if (len <= 1) return;
  for (int i = 0; i < len; ++i) s[i] = ++node_cnt;
  for (int i = 0; i < len; ++i) {
    add_edge((q[i].id << 1 | 0), (s[i] << 1 | 0));
    add_edge((s[i] << 1 | 1), (q[i].id << 1 | 1));
    if (i + 1 < len) {
      add_edge((s[i] << 1 | 0), (s[i + 1] << 1 | 0));
      add_edge((s[i + 1] << 1 | 1), (s[i] << 1 | 1));
      add_edge((s[i] << 1 | 0), (q[i + 1].id << 1 | 1));
      add_edge((q[i + 1].id << 1 | 0), (s[i] << 1 | 1));
    }
  }
}
void tarjan(int u) {
  dfn[u] = low[u] = ++dfs_clock;
  stk[++stp] = u;
  ins[u] = 1;
  for (int i = h[u], v; i; i = e[i].nex) {
    if (!dfn[v = e[i].to]) {
      tarjan(v);
      low[u] = min(low[u], low[v]);
    } else if (ins[v])
      low[u] = min(low[u], dfn[v]);
  }
  if (dfn[u] == low[u]) {
    ++scc_cnt;
    do {
      sccno[u] = scc_cnt;
      u = stk[stp--];
      ins[u] = 0;
    } while (low[u] != dfn[u]);
  }
}
inline bool check(int k) {
  node_cnt = m;
  edge_cnt = 0;
  memset(h, 0, sizeof(h));
  memset(tag, 0, sizeof(tag));
  for (int u = 1; u <= n; ++u) {
    q[0].clear();
    col.clear();
    for (auto o : edge[u]) {
      if (o.v > k) {
        if (!tag[o.id]) {
          tag[o.id] = 1;
          add_edge((o.id << 1 | 1), (o.id << 1 | 0));
        }
      }
      q[0].push_back(o);
      q[o.c].push_back(o);
      col.push_back(o.c);
    }
    std::sort(col.begin(), col.end());
    col.erase(std::unique(col.begin(), col.end()), col.end());
    solve1(q[0]);
    for (auto c : col) solve2(q[c]);
    for (auto c : col) q[c].clear();
  }
  dfs_clock = stp = scc_cnt = 0;
  memset(dfn, 0, sizeof(dfn));
  for (int u = 1; u <= node_cnt; ++u) {
    if (!dfn[(u << 1 | 0)]) tarjan((u << 1 | 0));
    if (!dfn[(u << 1 | 1)]) tarjan((u << 1 | 1));
  }
  for (int u = 1; u <= m; ++u) {
    if (sccno[(u << 1 | 0)] == sccno[(u << 1 | 1)]) return 0;
  }
  return 1;
}
int main() {
  n = read();
  m = read();
  for (int i = 1, u, v, col; i <= m; ++i) {
    u = read();
    v = read();
    col = read();
    val[i] = read();
    t1[++c1] = col;
    t2[++c2] = val[i];
    edge[u].push_back((Node){col, val[i], i});
    edge[v].push_back((Node){col, val[i], i});
  }
  std::sort(t1 + 1, t1 + 1 + c1);
  c1 = std::unique(t1 + 1, t1 + 1 + c1) - t1 - 1;
  std::sort(t2 + 1, t2 + 1 + c2);
  c2 = std::unique(t2 + 1, t2 + 1 + c2) - t2 - 1;
  for (int u = 1; u <= n; ++u) {
    for (int i = 0; i < (int)edge[u].size(); ++i) {
      edge[u][i].c = std::lower_bound(t1 + 1, t1 + 1 + c1, edge[u][i].c) - t1;
      edge[u][i].v = std::lower_bound(t2 + 1, t2 + 1 + c2, edge[u][i].v) - t2;
    }
    std::sort(edge[u].begin(), edge[u].end());
  }
  int l = 1, r = c2, mid;
  while (l < r) {
    mid = (l + r) / 2;
    if (check(mid))
      r = mid;
    else
      l = mid + 1;
  }
  if (check(l)) {
    puts("Yes");
    int mx_val = 0;
    for (int i = 1; i <= m; ++i) {
      bool d = (sccno[(i << 1 | 0)] > sccno[(i << 1 | 1)]);
      if (d) que.push_back(i), chkmax(mx_val, val[i]);
    }
    printf("%d %d\n", mx_val, (int)que.size());
    for (auto v : que) printf("%d ", v);
  } else
    puts("No");
  return 0;
}
