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 long long LINF = 0x3f3f3f3f3f3f3f3f;
const int MOD = (int)1e9 + 7;
const int N = (int)5e5 + 7;
const long long over = (1ll << 32);
vector<int> g[N];
int nn;
void init(int _n) {
  for (int i = ((nn = _n << 1)) - 1; i >= (0); --i) g[i].clear();
}
int new_node() {
  for (int i = (0); i < (2); ++i) g[nn++].clear();
  return nn >> 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 del(int a, int va) {
  a = a << 1 | va;
  g[a ^ 1].pop_back();
}
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); }
int dfn[N], low[N], st[N], id[N];
int cc, _st, _;
void dfs(int c) {
  dfn[c] = low[c] = ++cc;
  st[_st++] = c;
  for (auto t : g[c]) {
    if (!dfn[t])
      dfs(t), 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, nn, cc = 0);
  fill_n(low, nn, _st = 0);
  fill_n(id, nn, _ = 0);
  for (int i = (0); i < (nn); ++i)
    if (!dfn[i]) dfs(i);
  for (int i = (0); i < (nn); ++i) --id[i];
  return;
}
int mark[N];
bool solve() {
  find();
  for (int i = 0; i < nn; i += 2) {
    if (id[i] == id[i + 1]) return 0;
    mark[i >> 1] = (id[i] > id[i + 1]);
  }
  return 1;
}
pair<pair<int, int>, int> p[N];
pair<int, int> e[N];
bool check(int x) {
  for (int i = (0); i < (nn); ++i)
    if (p[i].first.second > x) add_set(i, 0);
  int re = solve();
  for (int i = (0); i < (nn); ++i)
    if (p[i].first.second > x) del(i, 0);
  return re;
}
vector<int> ans;
int cnt[N], used[N];
void add_at_most_one(vector<pair<int, int> > vu) {
  int pre = -1;
  for (int i = (0); i < ((int)(vu).size()); ++i) {
    int a = vu[i].first, va = vu[i].second;
    int dpi = new_node();
    addEdge(a, va, dpi, 1);
    if (i) {
      addEdge(pre, 1, dpi, 1);
      addEdge(pre, 1, a, va ^ 1);
    }
    pre = dpi;
  }
}
vector<pair<int, int> > ban[N];
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = (0); i < (m); ++i) {
    scanf("%d%d%d%d", &e[i].first, &e[i].second, &p[i].first.first,
          &p[i].first.second);
    p[i].second = i;
  }
  sort(p, p + m);
  init(m);
  memset(cnt, -1, sizeof(cnt));
  for (int i = (0); i < (m); ++i) {
    int id = p[i].second;
    int u = e[id].first, v = e[id].second;
    ban[u].push_back(make_pair(i, 1));
    ban[v].push_back(make_pair(i, 1));
  }
  for (int i = (1); i < (n + 1); ++i) {
    if (n < 1000)
      add_at_most_one(ban[i]);
    else
      for (int j = (0); j < ((int)(ban[i]).size()); ++j) {
        for (int k = (j + 1); k < ((int)(ban[i]).size()); ++k) {
          int a = ban[i][j].first, b = ban[i][k].first;
          add_then(a, 1, b, 1);
        }
      }
  }
  for (int i = 0, j = 0; i < m; i = j) {
    while (j < m && p[i].first.first == p[j].first.first) j++;
    int c = p[i].first.first;
    for (int k = (i); k < (j); ++k) {
      int u = e[p[k].second].first, v = e[p[k].second].second;
      if (cnt[u] == j - 1)
        return 0 * printf("No\n");
      else if (cnt[u] >= i) {
        if (used[u]) return 0 * printf("No\n");
        used[u] = c;
        add_then(cnt[u], 0, k, 0);
        cnt[u] = j - 1;
      } else
        cnt[u] = k;
      if (cnt[v] == j - 1)
        return 0 * printf("No\n");
      else if (cnt[v] >= i) {
        if (used[v]) return 0 * printf("No\n");
        used[v] = c;
        add_then(cnt[v], 0, k, 0);
        cnt[v] = j - 1;
      } else
        cnt[v] = k;
    }
  }
  int l = 0, r = INF;
  while (l < r) {
    int m = (l + r) >> 1;
    if (check(m))
      r = m;
    else
      l = m + 1;
  }
  for (int i = (0); i < (m); ++i)
    if (p[i].first.second > l) add_set(i, 0);
  if (!solve()) return 0 * printf("No\n");
  printf("Yes\n");
  for (int i = (0); i < (m); ++i)
    if (mark[i]) ans.push_back(p[i].second);
  printf("%d %d\n", l, (int)(ans).size());
  sort((ans).begin(), (ans).end());
  for (int x : ans) {
    printf("%d ", x + 1);
  }
  printf("\n");
  return 0;
}
