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;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const long long maxn = 5e4 + 10;
const long long mod = 1e9 + 7;
const long double PI = acos((long double)-1);
long long pw(long long a, long long b, long long md = mod) {
  long long res = 1;
  while (b) {
    if (b & 1) {
      res = (a * res) % md;
    }
    a = (a * a) % md;
    b >>= 1;
  }
  return (res);
}
struct sat {
  int n;
  vector<vector<int> > in, out;
  vector<int> mark, col, topo;
  int c = 0;
  sat(int N)
      : n(N),
        in(n * 2 + 5),
        out(n * 2 + 5),
        mark(n * 2 + 5, 0),
        col(n * 2 + 5, 0) {}
  bool operator[](int x) { return (col[2 * x] > col[2 * x + 1]); };
  void add_edge(int v, int u) { in[u].push_back(v), out[v].push_back(u); }
  void add(int u, int v) { add_edge(v ^ 1, u), add_edge(u ^ 1, v); }
  void sfd(int v) {
    mark[v] = 1;
    col[v] = c;
    for (int u : in[v])
      if (!mark[u]) sfd(u);
  }
  void dfs(int v) {
    mark[v] = 1;
    for (int u : out[v])
      if (!mark[u]) dfs(u);
    topo.push_back(v);
  }
  inline bool validate() {
    for (int i = 1; i <= 2 * n + 1; i++)
      if (!mark[i]) dfs(i);
    reverse(topo.begin(), topo.end());
    memset(&mark[0], 0, sizeof(mark[0]) * mark.size());
    for (auto v : topo)
      if (!mark[v]) c++, sfd(v);
    for (int i = 1; i <= n; i++)
      if (col[2 * i] == col[2 * i + 1]) return (0);
    return (1);
  }
};
int n, m;
struct ed {
  int u, v, c, t, id;
};
vector<ed> e;
bool cmp(ed a, ed b) { return (a.t < b.t); }
int dup[maxn];
map<int, int> mp[maxn];
vector<pair<int, int> > adj[maxn];
bool chk(int x) {
  sat g(3 * m);
  int cur = m;
  for (int i = 1; i <= n; i++) {
    int k = 1;
    vector<pair<int, int> > vec;
    for (auto [u, j] : adj[i]) {
      ++cur;
      if (k > 1) g.add((cur - 1) * 2 + 1, cur * 2);
      if (e[j].c == dup[i] and j < x) vec.push_back({k, cur});
      k++;
    }
    if (vec.size() == 0) continue;
    if (vec.size() == 1) {
      int x = adj[i][vec[0].first - 1].second + 1;
      g.add(x * 2, x * 2);
      int y = vec[0].first;
      g.add(x * 2 + 1, y * 2);
    }
    if (vec.size() == 2) {
      int x = adj[i][vec[0].first - 1].second + 1;
      int y = vec[0].first;
      int X = adj[i][vec[1].first - 1].second + 1;
      int Y = vec[1].first;
      g.add(x * 2 + 1, y * 2);
      g.add(X * 2 + 1, Y * 2);
      g.add(X * 2, x * 2);
      g.add(X * 2 + 1, x * 2 + 1);
    }
  }
  for (int i = x + 1; i <= m; i++) g.add(i * 2 + 1, i * 2 + 1);
  if (!g.validate()) return (0);
  for (int i = 1; i <= n; i++) {
    if (!dup[i]) continue;
    bool ok = 0;
    for (auto [u, j] : adj[i])
      if (e[j].c == dup[i] and g[j + 1]) ok = 1;
    if (!ok) return (0);
  }
  return (1);
}
void solve(int x) {
  if (x == 0) cout << "0 0", exit(0);
  sat g(3 * m);
  int cur = m;
  for (int i = 1; i <= n; i++) {
    int k = 1;
    vector<pair<int, int> > vec;
    for (auto [u, j] : adj[i]) {
      ++cur;
      if (k > 1) g.add((cur - 1) * 2 + 1, cur * 2);
      if (e[j].c == dup[i] and j < x) vec.push_back({k, cur});
      k++;
    }
    if (vec.size() == 0) continue;
    if (vec.size() == 1) {
      int x = adj[i][vec[0].first - 1].second + 1;
      g.add(x * 2, x * 2);
      int y = vec[0].first;
      g.add(x * 2 + 1, y * 2);
    }
    if (vec.size() == 2) {
      int x = adj[i][vec[0].first - 1].second + 1;
      int y = vec[0].first;
      int X = adj[i][vec[1].first - 1].second + 1;
      int Y = vec[1].first;
      g.add(x * 2 + 1, y * 2);
      g.add(X * 2 + 1, Y * 2);
      g.add(X * 2, x * 2);
      g.add(X * 2 + 1, x * 2 + 1);
    }
  }
  for (int i = x + 1; i <= m; i++) g.add(i * 2 + 1, i * 2 + 1);
  g.validate();
  vector<int> ans;
  for (int i = 1; i <= m; i++)
    if (g[i]) ans.push_back(e[i - 1].id);
  cout << e[x - 1].t << ' ' << ans.size() << '\n';
  for (int x : ans) cout << x << ' ';
}
int32_t main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  for (int i = 0; i < m; i++)
    e.push_back({0, 0, 0, 0, 0}), cin >> e[i].u >> e[i].v >> e[i].c >> e[i].t,
        e[i].id = i + 1;
  sort(e.begin(), e.end(), cmp);
  int i = 0;
  for (auto [u, v, c, t, boz] : e) {
    mp[u][c]++, mp[v][c]++;
    if (mp[v][c] >= 2) {
      if (dup[v]) cout << "No", exit(0);
      dup[v] = c;
    }
    if (mp[u][c] >= 2) {
      if (dup[u]) cout << "No", exit(0);
      dup[u] = c;
    }
    adj[v].push_back({u, i});
    adj[u].push_back({v, i});
    i++;
  }
  if (!chk(m)) cout << "No", exit(0);
  int ans = m;
  for (int i = 20; i >= 0; i--) {
    if (ans - (1 << i) < 0) continue;
    ans -= (1 << i);
    if (!chk(ans)) ans += (1 << i);
  }
  cout << "Yes" << '\n';
  solve(ans);
  return (0);
}
