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;
vector<int> to[1000005];
int color[1000005];
int bnt;
namespace Tarjan {
int id[1000005];
int low[1000005];
int vis[1000005];
stack<int> STK;
int cnt;
void clear(int n) {
  for (int i = 1; i <= n; i++) {
    id[i] = low[i] = vis[i] = color[i] = 0;
  }
}
void tarjan(int x) {
  id[x] = low[x] = vis[x] = ++cnt;
  STK.push(x);
  for (auto N : to[x]) {
    if (!id[N])
      tarjan(N), low[x] = min(low[x], low[N]);
    else if (vis[N])
      low[x] = min(low[x], low[N]);
  }
  if (low[x] == id[x]) {
    int t = -1;
    bnt++;
    while (t ^ x) {
      t = STK.top();
      STK.pop();
      color[t] = bnt;
      vis[t] = false;
    }
  }
}
void rebuild(int n) {
  for (int i = 1; i <= n; i++)
    if (!id[i]) tarjan(i);
}
}  // namespace Tarjan
int n, m, cnt;
vector<int> bin[50005];
int co[50005];
struct edge {
  int u, v, c, w, id;
  edge(){};
  edge(int _id) {
    cin >> u >> v >> c >> w;
    id = _id;
    co[id] = c;
    bin[u].push_back(id);
    bin[v].push_back(id);
  }
  bool operator<(const edge& from) const { return w < from.w; }
};
vector<edge> E;
bool cmp(const int A, const int B) { return co[A] < co[B]; }
void add_edge(int u, int v) { to[u].push_back(v); }
void build_round(vector<int> V, int tow) {
  if (V.size() <= 1) return;
  int t = V.size();
  cnt++;
  for (int i = 0; i < t; i++) {
    add_edge(cnt + i + t * 0, V[i] + (m ^ tow));
    add_edge(cnt + i + t * 1, V[i] + (m ^ tow));
  }
  for (int i = 1; i < t; i++) {
    add_edge(cnt + i + t * 0, cnt + i + t * 0 - 1);
    add_edge(V[i] + tow, cnt + i + t * 0 - 1);
  }
  for (int i = 0; i < t - 1; i++) {
    add_edge(cnt + i + t * 1, cnt + i + t * 1 + 1);
    add_edge(V[i] + tow, cnt + i + t * 1 + 1);
  }
  cnt += t * 2;
}
bool check(int x) {
  bool f = 1;
  for (auto e : E)
    if (e.w > x) add_edge(e.id + m, e.id);
  Tarjan::clear(cnt);
  Tarjan::rebuild(cnt);
  for (int i = 1; i <= m; i++)
    if (color[i] == color[i + m]) f = false;
  for (auto e : E)
    if (e.w > x) to[e.id + m].pop_back();
  return f;
}
int main() {
  cin >> n >> m;
  cnt = m * 2;
  for (int i = 1; i <= m; i++) E.push_back(edge(i));
  sort(E.begin(), E.end());
  for (int i = 1; i <= n; i++) {
    sort(bin[i].begin(), bin[i].end(), cmp);
  }
  for (int i = 1; i <= n; i++) {
    build_round(bin[i], m);
  }
  for (int i = 1; i <= n; i++)
    if (bin[i].size()) {
      vector<int> T = vector<int>();
      int pre = co[bin[i][0]];
      for (auto c : bin[i]) {
        if (co[c] ^ pre) build_round(T, 0), T.clear(), pre = co[c];
        T.push_back(c);
      }
      build_round(T, 0);
    }
  int l = 0, r = 1e9 + 7;
  while (l ^ r) {
    int mid = (l + r) >> 1;
    if (mid == r) mid = l;
    if (check(mid))
      r = mid;
    else
      l = mid + 1;
  }
  if (l == 1e9 + 7) return cout << "No", 0;
  cout << "Yes\n";
  check(l);
  int ans = 0;
  for (auto e : E)
    if (color[e.id] > color[e.id + m]) ans++;
  cout << l << " " << ans << "\n";
  for (auto e : E)
    if (color[e.id] > color[e.id + m]) cout << e.id << " ";
  return 0;
}
