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 maxn = 250010;
const int inf = 1e9 + 10;
struct TwoSat {
  vector<vector<int> > G;
  vector<int> num, low, color;
  stack<int> st;
  int n, step;
  bool invalid;
  TwoSat(int n = 0) : n(n) {
    G.assign(n + maxn + 10, vector<int>());
    st = stack<int>();
    num.assign(n + maxn + 10, 0);
    low.assign(n + maxn + 10, 0);
    color.assign(n + maxn + 10, 0);
    step = 0;
    invalid = 0;
  }
  void addEdge(int u, int v) { G[u + maxn].push_back(v + maxn); }
  void setCondition(int u, int v) {
    addEdge(-u, v);
    addEdge(-v, u);
  }
  void assign(int u, int c) {
    u -= maxn;
    if (color[u + maxn] == 3 - c)
      invalid = 1;
    else
      color[u + maxn] = c;
    if (color[-u + maxn] == c)
      invalid = 1;
    else
      color[-u + maxn] = 3 - c;
  }
  void dfs(int u) {
    if (invalid) return;
    low[u] = num[u] = ++step;
    st.push(u);
    for (int v : G[u]) {
      if (num[v])
        low[u] = min(low[u], num[v]);
      else
        dfs(v), low[u] = min(low[u], low[v]);
      if (color[v] == 1) assign(u, 1);
    }
    if (low[u] == num[u]) {
      int v = 0;
      if (!color[u]) assign(u, 2);
      do {
        v = st.top();
        st.pop();
        low[v] = num[v] = inf;
        assign(v, color[u]);
      } while (v != u);
    }
  }
} ts;
int N, M;
vector<pair<int, int> > G[maxn];
map<int, int> cnt;
int c[maxn], t[maxn];
bool check(int x) {
  ts = TwoSat(3 * M);
  int tot = M;
  vector<int> mustFalse;
  for (int i = 1; i <= N; i++) {
    for (int j = 0; j < G[i].size(); j++) {
      int id = G[i][j].second, cl = G[i][j].first;
      if (t[id] > x) mustFalse.push_back(id);
      if (j > 0 && cl == G[i][j - 1].first)
        ts.setCondition(-id, -G[i][j - 1].second),
            ts.setCondition(id, G[i][j - 1].second);
      if (j > 0) {
        ts.addEdge(tot, -id);
        ts.addEdge(tot, tot + 1);
        ts.addEdge(id, -tot);
        ts.addEdge(-(tot + 1), -tot);
      }
      ++tot, ts.addEdge(id, tot), ts.addEdge(-tot, -id);
    }
  }
  for (int i : mustFalse) ts.assign(i + maxn, 1);
  for (int i = 1; i <= tot; i++)
    if (!ts.num[i + maxn]) ts.dfs(i + maxn);
  for (int i = 1; i <= tot; i++)
    if (!ts.num[-i + maxn]) ts.dfs(-i + maxn);
  return (!ts.invalid);
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> N >> M;
  for (int i = 1; i <= M; i++) {
    int u, v;
    cin >> u >> v >> c[i] >> t[i];
    G[u].push_back(pair<int, int>(c[i], i));
    G[v].push_back(pair<int, int>(c[i], i));
  }
  for (int i = 1; i <= N; i++) {
    int couple = 0;
    sort(G[i].begin(), G[i].end());
    for (int j = 0; j < G[i].size(); j++) {
      cnt[G[i][j].first]++;
      if (cnt[G[i][j].first] > 2)
        return printf("No\n"), 0;
      else if (cnt[G[i][j].first] == 2)
        couple++;
    }
    for (int j = 0; j < G[i].size(); j++) cnt[G[i][j].first]--;
    if (couple > 1) return printf("No\n"), 0;
  }
  int l = 0, r = 1e9;
  while (l != r) {
    int mid = ((l + r) >> 1);
    if (check(mid))
      r = mid;
    else
      l = mid + 1;
  }
  check(l);
  int cTrue = 0;
  for (int i = 1; i <= M; i++) cTrue += (ts.color[i + maxn] == 2);
  printf("Yes\n%d %d\n", l, cTrue);
  if (cTrue > 0) {
    for (int i = 1; i <= M; i++)
      if (ts.color[i + maxn] == 2) printf("%d ", i);
    printf("\n");
  }
}
