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 = 5e4 + 5, inf = INT_MAX / 2;
int n, m, t[MAXN], c[MAXN], uu[MAXN], vv[MAXN], tw[MAXN], tmpans = 0;
int tp[2], vp[2][2][MAXN], wp[2][2][MAXN];
vector<int> allt, vs, es, muste, pe[2][2][MAXN];
vector<pair<int, pair<int, int>>> adj[MAXN];
bool visit[MAXN], must[MAXN], can = true, m2[MAXN], bein[2][MAXN], mark[MAXN];
map<pair<int, int>, int> e1, e2;
set<pair<int, int>> tof;
void dfs(int v, int cl) {
  vs.push_back(v);
  int ee1 = e1[{cl, v}], ee2 = e2[{cl, v}];
  if (ee1 != 0 && !visit[ee1]) {
    es.push_back(ee1);
    visit[ee1] = true;
    if (vs[0] != (vv[ee1] == v ? uu[ee1] : vv[ee1]))
      dfs((vv[ee1] == v ? uu[ee1] : vv[ee1]), cl);
  }
  if (ee2 != 0 && !visit[ee2]) {
    es.push_back(ee2);
    visit[ee2] = true;
    if (vs[0] != (vv[ee2] == v ? uu[ee2] : vv[ee2]))
      dfs((vv[ee2] == v ? uu[ee2] : vv[ee2]), cl);
  }
  return;
}
inline void add(int ind) {
  vs.clear();
  es.clear();
  dfs(vv[ind], c[ind]);
  if ((int)vs.size() % 2 && (int)es.size() % 2) {
    can = false;
    return;
  }
  if ((int)vs.size() == (int)es.size()) {
    int mxx[2], ii;
    mxx[0] = mxx[1] = 0;
    for (int i = 0; i < (int)vs.size(); i++)
      must[vs[i]] = true, mxx[i % 2] = max(mxx[i % 2], t[es[i]]);
    ii = (mxx[0] <= mxx[1] ? 0 : 1);
    for (int i = ii; i < (int)es.size(); i += 2) muste.push_back(es[i]);
    tmpans = max(tmpans, min(mxx[0], mxx[1]));
    return;
  }
  if ((int)vs.size() <= 2) return;
  int ii = (int)vs.size() % 2;
  vp[ii][0][tp[ii]] = vs[0];
  vp[ii][1][tp[ii]] = vs.back();
  if (ii == 1)
    adj[vs[0]].push_back({vs.back(), {tp[ii], 0}}),
        adj[vs.back()].push_back({vs[0], {tp[ii], 1}});
  for (int i = 1; i < (int)vs.size() - 1; i++) must[vs[i]] = true;
  for (int i = 0; i < (int)es.size(); i++) {
    wp[ii][i % 2][tp[ii]] = max(wp[ii][i % 2][tp[ii]], t[es[i]]);
    pe[ii][i % 2][tp[ii]].push_back(es[i]);
  }
  tp[ii]++;
  return;
}
void dfs2(int v, int ww) {
  m2[v] = true;
  for (auto i : adj[v])
    if (!mark[i.second.first] && (m2[i.first] || must[i.first]) &&
        wp[1][i.second.second][i.second.first] <= ww) {
      mark[i.second.first] = true;
      bein[1][i.second.first] = i.second.second;
      return;
    }
  for (auto i : adj[v])
    if (!mark[i.second.first] && wp[1][i.second.second][i.second.first] <= ww) {
      mark[i.second.first] = true;
      bein[1][i.second.first] = i.second.second;
      if (!m2[i.first] && !must[i.first]) dfs2(i.first, ww);
      return;
    }
  return;
}
bool ch(int w) {
  for (int i = 0; i < n; i++) m2[i] = false;
  for (int i = 0; i < tp[1]; i++) mark[i] = false;
  for (int i = 0; i < tp[0]; i++) {
    if (wp[0][0][i] > w && wp[0][1][i] > w) return false;
    bein[0][i] = 1;
    if (wp[0][1][i] > w) {
      if (m2[vp[0][0][i]] || m2[vp[0][1][i]]) return false;
      m2[vp[0][0][i]] = m2[vp[0][1][i]] = true;
      bein[0][i] = 0;
    }
  }
  queue<int> bad;
  for (int i = 0; i < n; i++)
    if (must[i] || m2[i]) bad.push(i);
  while (!bad.empty()) {
    int v = bad.front();
    bad.pop();
    for (auto i : adj[v])
      if (!mark[i.second.first] &&
          wp[1][1 - i.second.second][i.second.first] <= w && !must[i.first] &&
          !m2[i.first]) {
        mark[i.second.first] = true;
        bein[1][i.second.first] = 1 - i.second.second;
        m2[i.first] = true;
        bad.push(i.first);
      }
  }
  for (int i = 0; i < tp[1]; i++) {
    if (wp[1][0][i] <= w && wp[1][1][i] > w && !mark[vp[1][0][i]] &&
        !m2[vp[1][0][i]]) {
      m2[vp[1][0][i]] = true;
      mark[i] = true;
      bein[1][i] = 0;
    }
    if (wp[1][0][i] > w && wp[1][1][i] <= w && !mark[vp[1][1][i]] &&
        !m2[vp[1][1][i]]) {
      m2[vp[1][1][i]] = true;
      mark[i] = true;
      bein[1][i] = 1;
    }
  }
  for (int i = 0; i < n; i++)
    if (!m2[i] && !must[i]) dfs2(i, w);
  for (int i = 0; i < tp[1]; i++)
    if (!mark[i]) return false;
  return true;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  set<int> st;
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    cin >> vv[i] >> uu[i] >> c[i] >> t[i];
    vv[i]--;
    uu[i]--;
    st.insert(t[i]);
    if (e2[{c[i], vv[i]}] || e2[{c[i], uu[i]}]) {
      cout << "No" << endl;
      return 0;
    }
    tof.insert({c[i], vv[i]});
    tof.insert({c[i], uu[i]});
    if (e2[{c[i], vv[i]}]) tof.erase({c[i], vv[i]});
    if (e2[{c[i], uu[i]}]) tof.erase({c[i], uu[i]});
    swap(e1[{c[i], vv[i]}], e2[{c[i], vv[i]}]);
    e1[{c[i], vv[i]}] = i;
    swap(e1[{c[i], uu[i]}], e2[{c[i], uu[i]}]);
    e1[{c[i], uu[i]}] = i;
    tw[vv[i]] += (e2[{c[i], vv[i]}] != 0);
    tw[uu[i]] += (e2[{c[i], uu[i]}] != 0);
    if (tw[vv[i]] > 1 || tw[uu[i]] > 1) {
      cout << "No" << endl;
      return 0;
    }
  }
  for (auto i : tof) {
    if (!visit[e1[{i.first, i.second}]]) add(e1[{i.first, i.second}]);
  }
  allt.push_back(0);
  for (int i : st) allt.push_back(i);
  if (!can) {
    cout << "No" << endl;
    return 0;
  }
  int l = 0, r = (int)allt.size();
  while (l < r) {
    if (l + 1 == r) {
      r = (ch(allt[l]) ? l : r);
      break;
    }
    int mid = (l + r) / 2;
    if (ch(allt[mid]))
      r = mid;
    else
      l = mid;
  }
  bool tof = ch(allt[r]);
  cout << "Yes" << endl;
  int ans = max(allt[r], tmpans);
  vector<int> eans;
  for (int i : muste) eans.push_back(i);
  for (int j = 0; j < 2; j++)
    for (int i = 0; i < tp[j]; i++)
      for (int ee : pe[j][bein[j][i]][i]) {
        eans.push_back(ee);
      }
  cout << ans << " " << (int)eans.size() << endl;
  for (int ee : eans) cout << ee << " ";
  cout << endl;
  return 0;
}
