#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 7, M = 10 * N;
int n, m, tot, l, r;
int dfn[M], low[M], tim, sta[M], top, vis[M], scc[M], cnt;
vector<int> ID[N], s, E[M], ans;
template <typename _Tp>
inline void IN(_Tp& x) {
  char ch;
  bool flag = 0;
  x = 0;
  while (ch = getchar(), !isdigit(ch))
    if (ch == '-') flag = 1;
  while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
  if (flag) x = -x;
}
struct P {
  int u, v, c, t;
  inline void in() { IN(u), IN(v), IN(c), IN(t), r = max(r, t); }
} G[N];
inline void work1() {
  int S, T;
  for (int i = 0; i < s.size(); i++) {
    int x = ::s[i], y = ::s[i] + m, s = ++tot, t = ++tot;
    E[x].push_back(s), E[t].push_back(y);
    if (i)
      E[S].push_back(s), E[t].push_back(T), E[S].push_back(y),
          E[x].push_back(T);
    S = s, T = t;
  }
  s.clear();
}
inline void work2() {
  int S, T;
  for (int i = 0; i < s.size(); i++) {
    int x = ::s[i], y = ::s[i] + m, s = ++tot, t = ++tot;
    E[s].push_back(x), E[y].push_back(t);
    if (i)
      E[s].push_back(S), E[T].push_back(t), E[y].push_back(S),
          E[T].push_back(x);
    S = s, T = t;
  }
  s.clear();
}
void Tarjan(int u) {
  dfn[u] = low[u] = ++tim, sta[++top] = u, vis[u] = true;
  for (auto t : E[u])
    if (!dfn[t])
      Tarjan(t), low[u] = min(low[u], low[t]);
    else if (vis[t])
      low[u] = min(low[u], dfn[t]);
  if (dfn[u] == low[u]) {
    vis[u] = false, scc[u] = ++cnt;
    while (u != sta[top--]) vis[sta[top + 1]] = false, scc[sta[top + 1]] = cnt;
  }
}
inline void clear(int x) {
  for (int i = 1; i <= m; ++i)
    if (G[i].t > x) E[i].pop_back();
}
inline bool check(int x) {
  for (int i = 1; i <= m; ++i)
    if (G[i].t > x) E[i].push_back(i + m);
  for (int i = 1; i <= tot; ++i) dfn[i] = 0;
  cnt = tim = 0;
  for (int i = 1; i <= tot; ++i)
    if (!dfn[i]) Tarjan(i);
  for (int i = 1; i <= m; ++i)
    if (scc[i] == scc[i + m]) return clear(x), 0;
  return clear(x), 1;
}
int main() {
  IN(n), IN(m), tot = m << 1;
  for (int i = 1; i <= m; ++i)
    G[i].in(), ID[G[i].u].push_back(i), ID[G[i].v].push_back(i);
  for (int i = 1; i <= n; ++i) {
    sort(ID[i].begin(), ID[i].end(),
         [&](int a, int b) { return G[a].c < G[b].c; });
    s = ID[i], work1();
    for (int l = 0, r = 0; l < ID[i].size(); l = ++r) {
      s.push_back(ID[i][l]);
      while (r + 1 < ID[i].size() && G[ID[i][r + 1]].c == G[ID[i][r]].c)
        s.push_back(ID[i][++r]);
      work2();
    }
  }
  if (!check(r)) return puts("No"), 0;
  puts("Yes");
  while (l < r)
    check(((l + r) >> 1)) ? r = ((l + r) >> 1) : l = ((l + r) >> 1) + 1;
  check(l);
  for (int i = 1; i <= m; ++i)
    if (scc[i] < scc[i + m]) ans.push_back(i);
  printf("%d %d\n", l, ans.size());
  for (auto num : ans) printf("%d ", num);
  return puts(""), 0;
}
