#include <bits/stdc++.h>
namespace modular {
const int MOD = 1000000007;
inline int add(int x, int y) { return (x += y) >= MOD ? x -= MOD : x; }
inline void inc(int &x, int y) { (x += y) >= MOD ? x -= MOD : 0; }
inline int mul(int x, int y) { return 1LL * x * y % MOD; }
inline int qpow(int x, int y) {
  int ans = 1;
  for (; y; y >>= 1, x = mul(x, x))
    if (y & 1) ans = mul(ans, x);
  return ans;
}
};  // namespace modular
namespace Base {
template <typename Tp>
inline Tp input() {
  Tp x = 0, y = 1;
  char c = getchar();
  while ((c < '0' || '9' < c) && c != EOF) {
    if (c == '-') y = -1;
    c = getchar();
  }
  if (c == EOF) return 0;
  while ('0' <= c && c <= '9') x = x * 10 + c - '0', c = getchar();
  return x *= y;
}
template <typename Tp>
inline void read(Tp &x) {
  x = input<Tp>();
}
template <typename Tp>
inline void chmax(Tp &x, Tp y) {
  x < y ? x = y : 0;
}
template <typename Tp>
inline void chmin(Tp &x, Tp y) {
  x > y ? x = y : 0;
}
};  // namespace Base
using namespace Base;
int N, M, tot;
std::vector<int> G[500007], sat[500007], tmp;
struct edge {
  int u, v, c, t;
  bool operator<(const edge &rhs) const { return c < rhs.c; }
} e[500007];
bool cmp(int x, int y) { return e[x] < e[y]; }
void make() {
  int s = -1, s2 = -1;
  for (int i : tmp) {
    int cs = ++tot, cs2 = ++tot;
    int x = i, x2 = i + M;
    sat[x].push_back(cs), sat[cs2].push_back(x2);
    if (s != -1)
      sat[s].push_back(cs), sat[s].push_back(x2), sat[cs2].push_back(s2),
          sat[x].push_back(s2);
    s = cs, s2 = cs2;
  }
  tmp.clear();
}
void make2() {
  int s = -1, s2 = -1;
  for (int i : tmp) {
    int cs = ++tot, cs2 = ++tot;
    int x = i, x2 = i + M;
    sat[cs].push_back(x), sat[x2].push_back(cs2);
    if (s != -1)
      sat[cs].push_back(s), sat[x2].push_back(s), sat[s2].push_back(cs2),
          sat[s2].push_back(x);
    s = cs, s2 = cs2;
  }
  tmp.clear();
}
int clk, cnt, dfn[500007], low[500007];
int st[500007], top;
int bl[500007];
void dfs(int x) {
  dfn[x] = low[x] = ++clk;
  st[++top] = x;
  for (int y : sat[x])
    if (!dfn[y]) {
      dfs(y);
      chmin(low[x], low[y]);
    } else if (!bl[y])
      chmin(low[x], dfn[y]);
  if (low[x] >= dfn[x]) {
    ++cnt;
    bl[x] = cnt;
    while (1) {
      int y = st[top--];
      if (y == x) break;
      bl[y] = cnt;
    }
  }
}
bool check(int mid) {
  for (int i = 1; i <= M; ++i)
    if (e[i].t > mid) sat[i].push_back(i + M);
  for (int i = 1; i <= tot; ++i) dfn[i] = bl[i] = 0;
  cnt = clk = top = 0;
  for (int i = 1; i <= tot; ++i)
    if (!dfn[i]) dfs(i);
  for (int i = 1; i <= M; ++i)
    if (e[i].t > mid) sat[i].pop_back();
  for (int i = 1; i <= M; ++i)
    if (bl[i] == bl[i + M]) return false;
  return true;
}
int main() {
  read(N), read(M);
  tot = M << 1;
  int l = 0, r = 0, mid, ans = -1;
  for (int i = 1; i <= M; ++i) {
    read(e[i].u), read(e[i].v), read(e[i].c), read(e[i].t);
    G[e[i].u].push_back(i), G[e[i].v].push_back(i);
    chmax(r, e[i].t);
  }
  for (int x = 1; x <= N; ++x) {
    std::sort(G[x].begin(), G[x].end(), cmp);
    tmp = G[x];
    make();
    for (int i = 0, j = 0; i < G[x].size(); i = j + 1) {
      j = i;
      tmp.push_back(G[x][i]);
      while (j + 1 < G[x].size() && e[G[x][i]].c == e[G[x][j + 1]].c)
        j++, tmp.push_back(G[x][j]);
      make2();
    }
  }
  if (!check(r)) return puts("No"), 0;
  puts("Yes");
  while (l <= r) {
    mid = l + r >> 1;
    if (check(mid))
      ans = mid, r = mid - 1;
    else
      l = mid + 1;
  }
  check(ans);
  top = 0;
  for (int i = 1; i <= M; ++i)
    if (bl[i] < bl[i + M]) st[++top] = i;
  printf("%d %d\n", ans, top);
  for (int i = 1; i <= top; ++i) printf("%d ", st[i]);
  puts("");
  return 0;
}
