#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
const int mod = 1e9 + 7;
struct edge {
  int u, v, t, c, id;
} e[N];
int n, m;
vector<edge> s[N];
bool cmp(edge a, edge b) { return a.c < b.c; }
struct TwoSat {
  static const int N = ::N << 1;
  int dfn[N], low[N], id[N], st[N], _st, _, cc;
  vector<int> g[N];
  int mark[N], n;
  void init(int _n) {
    for (int i = ((n = _n << 1)) - 1; i >= (0); --i) g[i].clear();
  }
  int new_node() {
    for (int i = (0); i < (2); i++) g[n++].clear();
    return n / 2 - 1;
  }
  void addedge(int a, int va, int b, int vb) {
    a = a << 1 | va;
    b = b << 1 | vb;
    g[a].push_back(b);
    g[b ^ 1].push_back(a ^ 1);
  }
  void add_set(int a, int va) {
    a = a << 1 | va;
    g[a ^ 1].push_back(a);
  }
  void add_then(int a, int va, int b, int vb) { addedge(a, va, b, vb ^ 1); }
  void add_or(int a, int va, int b, int vb) { addedge(a, va ^ 1, b, vb); }
  void add_xor(int a, int va, int b, int vb) {
    addedge(a, va, b, vb);
    addedge(b, vb, a, va);
  }
  void dfs(int c, vector<int> g[]) {
    dfn[c] = low[c] = ++cc;
    st[_st++] = c;
    for (auto t : g[c])
      if (!dfn[t])
        dfs(t, g), low[c] = min(low[c], low[t]);
      else if (!id[t])
        low[c] = min(low[c], dfn[t]);
    if (low[c] == dfn[c]) {
      ++_;
      do {
        id[st[--_st]] = _;
      } while (st[_st] != c);
    }
  }
  void find() {
    fill_n(dfn, n, cc = 0);
    fill_n(low, n, _st = 0);
    fill_n(id, n, _ = 0);
    for (int i = (0); i < (n); i++)
      if (!dfn[i]) dfs(i, g);
    for (int i = (0); i < (n); i++) --id[i];
    return;
  }
  bool solve() {
    find();
    for (int i = 0; i < n; i += 2) {
      if (id[i] == id[i + 1]) return 0;
      mark[i >> 1] = (id[i] > id[i + 1]);
    }
    return 1;
  }
} ts;
int p = 0;
void solve(int u) {
  sort(s[u].begin(), s[u].end(), cmp);
  for (int i = 0, j; i < (int)s[u].size();) {
    j = i;
    while (j < (int)s[u].size() && s[u][j].c == s[u][i].c) j++;
    if (j - i >= 3) {
      cout << "No\n";
      exit(0);
    }
    if (j - i == 2) {
      int x = s[u][i].id, y = s[u][i + 1].id;
      ts.add_or(x, 0, y, 0);
    }
    i = j;
  }
  for (int i = (0); i < ((int)s[u].size() - 1); i++) {
    ts.addedge(p + i + 1, 0, p + i, 0);
  }
  for (int i = (0); i < ((int)s[u].size()); i++) {
    int x = s[u][i].id;
    ts.addedge(x, 0, p + i, 0);
    if (i != (int)s[u].size() - 1) ts.addedge(x, 0, p + i + 1, 1);
  }
}
void link() {
  p = m;
  for (int i = (1); i < (n + 1); i++) {
    solve(i);
    p += (int)s[i].size();
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> m;
  int L = 0, R = 0;
  for (int i = (1); i < (m + 1); i++) {
    cin >> e[i].u >> e[i].v >> e[i].c >> e[i].t;
    e[i].id = i - 1;
    R = max(R, e[i].t);
    s[e[i].u].push_back(e[i]);
    s[e[i].v].push_back(e[i]);
  }
  int ans = -1;
  while (L <= R) {
    int mid = (L + R) / 2;
    ts.init(3 * m);
    link();
    for (int i = (1); i < (m + 1); i++)
      if (e[i].t > mid) {
        ts.add_set(e[i].id, 1);
      }
    if (ts.solve()) {
      ans = mid;
      R = mid - 1;
    } else
      L = mid + 1;
  }
  if (ans == -1)
    cout << "No";
  else {
    ts.init(3 * m);
    link();
    for (int i = (1); i < (m + 1); i++)
      if (e[i].t > ans) ts.add_set(e[i].id, 1);
    ts.solve();
    cout << "Yes\n";
    vector<int> task;
    for (int i = 0; i < m; ++i)
      if (!ts.mark[i]) task.push_back(i + 1);
    cout << ans << " " << (int)task.size() << "\n";
    for (auto v : task) cout << v << " ";
  }
  return 0;
}
