#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 10;
int n, m;
struct Edge {
  int u, v, c, t;
} es[maxn];
vector<int> vg[maxn];
vector<pair<int, int> > cg[maxn];
void add_edge(int u, int v, int c, int idx) {
  vg[u].push_back(idx);
  cg[u].push_back({c, idx});
}
struct twosat {
  int low[maxn], dfn[maxn], color[maxn], cnt, scc_cnt;
  bool instack[maxn];
  vector<int> g[maxn];
  stack<int> st;
  void init() {
    cnt = scc_cnt = 0;
    for (int i = 0; i <= 10 * m; i++) {
      dfn[i] = 0;
      g[i].clear();
    }
  }
  void Tarjan(int u) {
    low[u] = dfn[u] = ++cnt;
    st.push(u);
    instack[u] = true;
    for (const auto &v : g[u]) {
      if (!dfn[v])
        Tarjan(v), low[u] = min(low[u], low[v]);
      else if (instack[v])
        low[u] = min(low[u], dfn[v]);
    }
    if (low[u] == dfn[u]) {
      ++scc_cnt;
      do {
        color[u] = scc_cnt;
        u = st.top();
        st.pop();
        instack[u] = false;
      } while (low[u] != dfn[u]);
    }
  }
  inline void add(int a, int b) { g[a].push_back(b); }
  void build(int o) {
    init();
    for (int i = 1; i <= m; i++)
      if (es[i].t > o) add(i, i + m);
    int pre = 2 * m;
    for (int i = 1; i <= n; i++) {
      int las = -1;
      for (int p : vg[i]) {
        pre++;
        add(p, pre);
        add(pre + 2 * m, p + m);
        if (~las)
          add(p, las + 2 * m), add(las, p + m), add(las, pre),
              add(pre + 2 * m, las + 2 * m);
        las = pre;
      }
    }
    pre = 6 * m;
    for (int i = 1; i <= n; i++) {
      int lascol = -1, las = -1;
      for (auto p : cg[i]) {
        if (p.first != lascol) las = -1;
        pre++;
        add(p.second + m, pre + 2 * m), add(pre, p.second);
        if (~las)
          add(p.second + m, las), add(las + 2 * m, p.second),
              add(las + 2 * m, pre + 2 * m), add(pre, las);
        las = pre, lascol = p.first;
      }
    }
  }
  bool check(int o) {
    build(o);
    for (int i = 1; i <= 10 * m; i++)
      if (!dfn[i]) Tarjan(i);
    for (int i = 1; i <= m; i++)
      if (color[i] == color[i + m]) return false;
    for (int i = 2 * m + 1; i <= 4 * m; i++)
      if (color[i] == color[i + 2 * m]) return false;
    for (int i = 6 * m + 1; i <= 8 * m; i++)
      if (color[i] == color[i + 2 * m]) return false;
    return true;
  }
  void getRes(int res) {
    puts("Yes");
    check(res);
    int cnt = 0;
    for (int i = 1; i <= m; i++)
      if (color[i] < color[i + m]) cnt++;
    printf("%d %d\n", res, cnt);
    for (int i = 1; i <= m; i++)
      if (color[i] < color[i + m]) printf("%d ", i);
  }
} ts;
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d%d%d", &es[i].u, &es[i].v, &es[i].c, &es[i].t);
    add_edge(es[i].u, es[i].v, es[i].c, i);
    add_edge(es[i].v, es[i].u, es[i].c, i);
  }
  for (int i = 1; i <= n; i++) sort(cg[i].begin(), cg[i].end());
  int l = 0, r = 1e9, res = -1;
  while (l <= r) {
    int mid = l + r >> 1;
    if (ts.check(mid))
      r = mid - 1, res = mid;
    else
      l = mid + 1;
  }
  if (res == -1) return 0 * puts("No");
  ts.getRes(res);
  return 0;
}
