#include <bits/stdc++.h>
int MOD = int(1e9) + 7;
inline int add(int a, int b) {
  return (a + b >= MOD) ? (a + b - MOD) : (a + b);
}
inline void inc(int &a, int b) { a = add(a, b); }
inline int sub(int a, int b) { return (a - b < 0) ? (a - b + MOD) : (a - b); }
inline void dec(int &a, int b) { a = sub(a, b); }
inline int mul(int a, int b) { return (a * 1ll * b) % MOD; }
using namespace std;
const int MAX = 50005;
vector<int> edges[MAX];
int from[MAX], to[MAX], color[MAX], cost[MAX];
bool cmp(int x, int y) { return (color[x] < color[y]); }
vector<pair<int, int> > bads;
vector<int> adj[8 * MAX], tmp[8 * MAX];
int n, m, sz;
void init() {
  for (int i = 0; i < 8 * MAX; i++) adj[i].clear();
  for (int i = 0; i < (int)bads.size(); i++) {
    int id1 = bads[i].first, id2 = bads[i].second;
    adj[2 * id1].push_back(2 * id2 + 1);
    adj[2 * id2].push_back(2 * id1 + 1);
  }
  sz = m;
  for (int v = 0; v < n; v++)
    if (!edges[v].empty()) {
      int last = edges[v][0];
      for (int i = 1; i < (int)edges[v].size(); i++) {
        int id = edges[v][i];
        adj[2 * last + 1].push_back(2 * id);
        adj[2 * id + 1].push_back(2 * last);
        adj[2 * id + 1].push_back(2 * sz + 1);
        adj[2 * sz].push_back(2 * id);
        adj[2 * last + 1].push_back(2 * sz + 1);
        adj[2 * sz].push_back(2 * last);
        last = sz++;
      }
    }
}
vector<int> tp;
bool mark[8 * MAX];
void dfs(int v) {
  mark[v] = true;
  for (int i = 0; i < (int)adj[v].size(); i++) {
    int u = adj[v][i];
    if (!mark[u]) dfs(u);
  }
  tp.push_back(v);
}
int cc[8 * MAX];
void sfd(int v, int col) {
  mark[v] = true;
  cc[v] = col;
  for (int i = 0; i < (int)adj[v].size(); i++) {
    int u = adj[v][i];
    if (!mark[u]) sfd(u, col);
  }
}
vector<int> ans;
bool check(int lim) {
  init();
  sz *= 2;
  for (int i = 0; i < m; i++)
    if (cost[i] > lim) adj[2 * i + 1].push_back(2 * i);
  memset(mark, false, sizeof(mark));
  tp.clear();
  for (int i = 0; i < sz; i++)
    if (!mark[i]) dfs(i);
  reverse(tp.begin(), tp.end());
  for (int i = 0; i < sz; i++) tmp[i].clear();
  for (int v = 0; v < sz; v++)
    for (int i = 0; i < (int)adj[v].size(); i++) tmp[adj[v][i]].push_back(v);
  for (int i = 0; i < sz; i++) adj[i] = tmp[i];
  int cnt = 0;
  memset(mark, false, sizeof(mark));
  for (int i = 0; i < (int)tp.size(); i++)
    if (!mark[tp[i]]) sfd(tp[i], cnt++);
  ans.clear();
  for (int i = 0; i < sz / 2; i++) {
    if (cc[2 * i] == cc[2 * i + 1]) return false;
    if (i < m && cc[2 * i] < cc[2 * i + 1]) ans.push_back(i);
  }
  return true;
}
int main() {
  ios::sync_with_stdio(false);
  cin >> n >> m;
  vector<int> vals;
  vals.push_back(0);
  for (int i = 0; i < m; i++) {
    cin >> from[i] >> to[i] >> color[i] >> cost[i];
    vals.push_back(cost[i]);
    from[i]--;
    to[i]--;
    edges[from[i]].push_back(i);
    edges[to[i]].push_back(i);
  }
  for (int v = 0; v < n; v++) {
    sort(edges[v].begin(), edges[v].end(), cmp);
    int cnt = 0;
    for (int i = 0; i < (int)edges[v].size(); i++) {
      int j = i + 1;
      while (j < (int)edges[v].size() &&
             color[edges[v][j - 1]] == color[edges[v][j]])
        j++;
      if (j - i > 2) {
        cout << "No\n";
        return 0;
      }
      if (j - i == 2) {
        cnt++;
        if (cnt == 2) {
          cout << "No\n";
          return 0;
        }
        bads.push_back(make_pair(edges[v][i], edges[v][i + 1]));
        i++;
      }
    }
  }
  sort(vals.begin(), vals.end());
  vals.resize(unique(vals.begin(), vals.end()) - vals.begin());
  int l = -1, r = (int)vals.size();
  while (r - l > 1) {
    int mid = (l + r) / 2;
    if (check(vals[mid]))
      r = mid;
    else
      l = mid;
  }
  if (r == (int)vals.size()) {
    cout << "No\n";
    return 0;
  }
  check(vals[r]);
  cout << "Yes\n";
  cout << vals[r] << " " << ans.size() << "\n";
  for (int i = 0; i < (int)ans.size(); i++) cout << ans[i] + 1 << " ";
  cout << "\n";
  return 0;
}
