#include <bits/stdc++.h>
using namespace std;
long long power(long long a, long long b, long long md) {
  return (!b ? 1
             : (b & 1 ? a * power(a * a % md, b / 2, md) % md
                      : power(a * a % md, b / 2, md) % md));
}
const int xn = 5e5 + 10;
const int xm = -20 + 10;
const int SQ = 450;
const int inf = 1e9 + 10;
const long long INF = 1e18 + 10;
const int mod = 998244353;
const int base = 257;
int n, m, ptr, tohi, col[xn], a[xn], cnt;
vector<pair<int, int> > adj[xn];
stack<pair<int, int> > st;
vector<int> ans, topo, G[2][xn], part[xn];
bool mark[xn];
void add(int v, int u) {
  G[0][v].push_back(u);
  G[1][u].push_back(v);
  G[0][u ^ 1].push_back(v ^ 1);
  G[1][v ^ 1].push_back(u ^ 1);
  st.push({v, u});
}
void DFS(int v) {
  mark[v] = true;
  for (int u : G[0][v])
    if (!mark[u]) DFS(u);
  topo.push_back(v);
}
void SFD(int v, int c) {
  mark[v] = true;
  col[v] = c;
  for (int u : G[1][v])
    if (!mark[u]) SFD(u, c);
}
bool check(int x) {
  while (int(st.size())) {
    int v = st.top().first, u = st.top().second;
    st.pop();
    G[1][v ^ 1].pop_back();
    G[0][u ^ 1].pop_back();
    G[1][u].pop_back();
    G[0][v].pop_back();
  }
  for (int i = 1; i <= n; ++i)
    for (pair<int, int> u : adj[i])
      if (a[u.second] > x) add(u.second << 1, u.second << 1 | 1);
  memset(mark, false, sizeof mark);
  topo.clear();
  for (int i = 2; i <= ptr + ptr + 1; ++i)
    if (!mark[i]) DFS(i);
  reverse(topo.begin(), topo.end());
  memset(mark, false, sizeof mark);
  cnt = 0;
  for (int i : topo)
    if (!mark[i]) SFD(i, cnt++);
  for (int i = 1; i <= ptr; ++i)
    if (col[i << 1] == col[i << 1 | 1]) return false;
  return true;
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ;
  cin >> n >> m;
  ptr = m;
  for (int i = 1; i <= m; ++i) {
    int v, u, t, c;
    cin >> v >> u >> c >> t;
    a[i] = t;
    adj[v].push_back({c, i});
    adj[u].push_back({c, i});
    part[v].push_back(++ptr);
    part[u].push_back(++ptr);
  }
  for (int i = 1; i <= n; ++i) {
    sort(adj[i].begin(), adj[i].end());
    int ind = 0, ted = 0;
    for (int j = 0; j < int(adj[i].size()); ++j) {
      add(part[i][j] << 1, adj[i][j].second << 1 | 1);
      if (j) {
        add(part[i][j] << 1, part[i][j - 1] << 1);
        add(adj[i][j].second << 1, part[i][j - 1] << 1);
        if (adj[i][j].first == adj[i][j - 1].first) ++ted, ind = j;
      }
    }
    if (ted > 1) return cout << "No" << '\n', 0;
    if (ind) {
      add(adj[i][ind - 1].second << 1 | 1, adj[i][ind].second << 1);
      add(adj[i][ind - 1].second << 1, adj[i][ind].second << 1 | 1);
    }
  }
  while (int(st.size())) st.pop();
  int l = -1, r = inf;
  while (r - l > 1) {
    int mid = l + r >> 1;
    if (check(mid))
      r = mid;
    else
      l = mid;
  }
  if (r == inf) return cout << "No" << '\n', 0;
  check(r);
  cout << "Yes" << '\n';
  for (int i = 1; i <= m; ++i)
    if (col[i << 1] > col[i << 1 | 1]) ans.push_back(i);
  cout << r << ' ' << int(ans.size()) << '\n';
  for (int x : ans) cout << x << ' ';
  cout << '\n';
  return 0;
}
