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 N = 5e4 + 10, MX = 6 * N;
int n, m, sz, cnt[N << 1];
struct edge {
  int u, v, c, t;
  edge(int u, int v, int c, int t) : u(u), v(v), c(c), t(t) {}
};
vector<edge> ed;
vector<int> mp, vec[N], g[MX], rev[MX], st;
bool mark[MX], seen[MX], x[MX];
void fail() {
  cout << "No";
  exit(0);
}
void out(int t) {
  cout << "Yes\n";
  int k = 0;
  for (int i = 0; i < m; i++) k += (x[i] == 1);
  cout << t << " " << k << "\n";
  for (int i = 0; i < m; i++)
    if (x[i]) cout << i + 1 << " ";
  exit(0);
}
void clr() {
  for (int i = 0; i < MX; i++) g[i].clear(), rev[i].clear();
  st.clear();
  memset(mark, 0, sizeof mark);
  memset(seen, 0, sizeof seen);
  memset(x, 0, sizeof x);
}
void add_edge(int u, int v) {
  g[u].push_back(v);
  rev[v].push_back(u);
}
void add_clause(int u, int v) {
  add_edge(u ^ 1, v);
  add_edge(v ^ 1, u);
}
void dfs(int v, vector<int>* g, vector<int>& nodes) {
  if (mark[v]++) return;
  for (auto u : g[v]) dfs(u, g, nodes);
  nodes.push_back(v);
}
vector<pair<int, int> > Q;
bool check(int w) {
  clr();
  for (auto cl : Q) add_clause(cl.first, cl.second);
  for (int i = 0; i < m; i++)
    if (ed[i].t > w) add_edge(i << 1 | 1, i << 1);
  for (int v = 0; v < (sz << 1); v++)
    if (!mark[v]) dfs(v, g, st);
  memset(mark, 0, sizeof mark);
  for (; st.size(); st.pop_back()) {
    int v = st.back();
    vector<int> comp;
    dfs(v, rev, comp);
    for (auto u : comp) {
      seen[u] = 1;
      if (seen[u ^ 1]) return false;
      x[u >> 1] = (u & 1);
    }
    for (auto u : comp) seen[u] = 0;
  }
  return true;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  for (int i = 0; i < m; i++) {
    int u, v, c, t;
    cin >> u >> v >> c >> t;
    u--, v--;
    ed.push_back({u, v, c, t});
    vec[v].push_back(i);
    vec[u].push_back(i);
    mp.push_back(c);
  }
  sort(mp.begin(), mp.end());
  mp.resize(unique(mp.begin(), mp.end()) - mp.begin());
  for (int i = 0; i < m; i++) {
    ed[i].c = lower_bound(mp.begin(), mp.end(), ed[i].c) - mp.begin();
  }
  mp.clear();
  for (int i = 0; i < m; i++) mp.push_back(ed[i].t);
  sort(mp.begin(), mp.end());
  mp.resize(unique(mp.begin(), mp.end()) - mp.begin());
  for (int i = 0; i < m; i++)
    ed[i].t = lower_bound(mp.begin(), mp.end(), ed[i].t) - mp.begin();
  sz = m;
  for (int v = 0; v < n; v++) {
    for (int j = 0; j < vec[v].size(); j++) {
      int i = vec[v][j];
      cnt[ed[i].c]++;
      if (cnt[ed[i].c] > 2) fail();
      if (cnt[ed[i].c] == 2) {
        int y = cnt[ed[i].c + N];
        Q.push_back({i << 1 | 1, y << 1 | 1});
      }
      Q.push_back({i << 1, sz << 1 | 1});
      if (j) {
        Q.push_back({(sz - 1) << 1, sz << 1 | 1});
        Q.push_back({(sz - 1) << 1, i << 1});
      }
      sz++;
      cnt[ed[i].c + N] = i;
    }
    for (auto i : vec[v]) cnt[ed[i].c + N] = cnt[ed[i].c] = 0;
  }
  int lo = -1, hi = mp.size() - 1;
  if (!check(hi)) fail();
  if (check(lo)) out(0);
  while (hi - lo > 1) {
    int mid = (hi + lo) / 2;
    if (check(mid))
      hi = mid;
    else
      lo = mid;
  }
  out(mp[hi]);
}
