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;
void SR(int &x) { scanf("%d", &x); }
void SR(long long &x) { scanf("%lld", &x); }
void SR(double &x) { scanf("%lf", &x); }
void SR(char *s) { scanf("%s", s); }
void RI() {}
template <typename I, typename... T>
void RI(I &x, T &...tail) {
  SR(x);
  RI(tail...);
}
void SP(const int x) { printf("%d", x); }
void SP(const long long x) { printf("%lld", x); }
void SP(const double x) { printf("%.16lf", x); }
void SP(const char *s) { printf(s); }
void PS() { puts(""); }
template <typename I, typename... T>
void PS(I &x, T &...tail) {
  putchar(' ');
  SP(x);
  PS(tail...);
}
void PL() { puts(""); }
template <typename I, typename... T>
void PL(const I x, const T... tail) {
  SP(x);
  PS(tail...);
}
template <size_t maxn>
struct Sat {
  vector<int> edge[2 * maxn], re[2 * maxn];
  int n;
  void add(int p, int x, int q, int y) {
    int u = p << 1 | x, v = q << 1 | y;
    edge[u].push_back(v);
    edge[v ^ 1].push_back(u ^ 1);
    re[v].push_back(u);
    re[u ^ 1].push_back(v ^ 1);
  }
  void undo(int p, int x, int q, int y) {
    int u = p << 1 | x, v = q << 1 | y;
    edge[u].pop_back();
    edge[v ^ 1].pop_back();
    re[v].pop_back();
    re[u ^ 1].pop_back();
  }
  int app() { return n++; }
  bitset<2 * maxn> vis;
  void dfs1(int u, vector<int> &r) {
    vis[u] = 1;
    for (auto v : edge[u])
      if (!vis[v]) dfs1(v, r);
    r.push_back(u);
  }
  int id[2 * maxn];
  void dfs2(int u, int p) {
    vis[u] = 1;
    id[u] = p;
    for (auto v : re[u])
      if (!vis[v]) dfs2(v, p);
  }
  bitset<2 * maxn> ans;
  void zet(int u, bool x) {
    vis[u] = 1;
    ans[u] = x;
    for (auto v : re[u])
      if (!vis[v] && id[v] == id[u]) zet(v, x);
  }
  bool ask(int p) { return ans[p << 1]; }
  bool sol() {
    vector<int> ret;
    vis.reset();
    for (int i = 0; i < int(2 * n); i++)
      if (!vis[i]) dfs1(i, ret);
    reverse(begin(ret), end(ret));
    vis.reset();
    for (auto u : ret)
      if (!vis[u]) dfs2(u, u);
    for (int p = 0; p < int(n); p++)
      if (id[p << 1] == id[p << 1 | 1]) return false;
    vis.reset();
    for (auto u : ret)
      if (id[u] == u && !vis[u]) zet(u, 1), zet(u ^ 1, 0);
    return true;
  }
};
Sat<int(2.5e5 + 5)> sat;
const int maxn = 5e4 + 4;
int n, m;
vector<int> edge[maxn];
pair<int, int> sid[maxn];
int c[maxn], t[maxn];
void read() {
  RI(n, m);
  for (int i = 0; i < int(m); i++) {
    int u, v;
    RI(u, v, c[i], t[i]);
    edge[u].push_back(i);
    edge[v].push_back(i);
    sid[i] = make_pair(u, v);
  }
}
int build() {
  sat.n = m;
  for (int u = (1); u <= int(n); u++) {
    auto &e = edge[u];
    map<int, int> col;
    for (auto i : e) col[c[i]]++;
    int c2 = 0;
    for (auto p : col)
      if (p.second > 2) return 1;
    for (auto p : col)
      if (p.second == 2) c2++;
    if (c2 >= 2) return 1;
    static int pre[maxn], suf[maxn];
    int siz = ((int)(e).size());
    for (int i = 0; i < int(siz); i++) pre[i] = sat.app();
    for (int i = 0; i < int(siz); i++) suf[i] = sat.app();
    sat.add(e[0], 1, pre[0], 1);
    sat.add(e[0], 0, pre[0], 0);
    for (int i = (1); i <= int(siz - 1); i++) {
      sat.add(e[i], 1, pre[i], 1);
      sat.add(pre[i - 1], 1, pre[i], 1);
    }
    sat.add(e[siz - 1], 1, suf[siz - 1], 1);
    sat.add(e[siz - 1], 0, suf[siz - 1], 0);
    for (int i = siz - 2; i >= 0; i--) {
      sat.add(e[i], 1, suf[i], 1);
      sat.add(suf[i + 1], 1, suf[i], 1);
    }
    for (int i = 0; i < int(siz); i++) {
      if (i > 0) sat.add(e[i], 1, pre[i - 1], 0);
      if (i < siz - 1) sat.add(e[i], 1, suf[i + 1], 0);
    }
    if (c2 == 1) {
      vector<int> v;
      for (auto i : e)
        if (col[c[i]] == 2) v.push_back(i);
      assert(((int)(v).size()) == 2);
      sat.add(v[0], 1, v[1], 0);
      sat.add(v[0], 0, v[1], 1);
    }
  }
  return 0;
}
bool test(int k) {
  for (int i = 0; i < int(m); i++)
    if (t[i] > k) sat.add(i, 1, i, 0);
  bool ans = sat.sol();
  for (int i = 0; i < int(m); i++)
    if (t[i] > k) sat.undo(i, 1, i, 0);
  return ans;
}
void sol() {
  int l = 1, r = 1e9 + 7;
  while (r > l) {
    int mid = (l + r) / 2;
    if (test(mid))
      r = mid;
    else
      l = mid + 1;
  }
  if (l > 1e9)
    PL("No");
  else {
    PL("Yes");
    int cnt = 0;
    for (int i = 0; i < int(m); i++) cnt += sat.ask(i);
    PL(l, cnt);
    for (int i = 0; i < int(m); i++)
      if (sat.ask(i)) printf("%d ", i + 1);
  }
}
int main() {
  read();
  if (!build())
    sol();
  else
    PL("No");
  return 0;
}
