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;
template <typename T, typename S>
inline bool upmin(T& a, const S& b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T, typename S>
inline bool upmax(T& a, const S& b) {
  return a < b ? a = b, 1 : 0;
}
template <typename N, typename PN>
inline N flo(N a, PN b) {
  return a >= 0 ? a / b : -((-a - 1) / b) - 1;
}
template <typename N, typename PN>
inline N cei(N a, PN b) {
  return a > 0 ? (a - 1) / b + 1 : -(-a / b);
}
template <typename N>
N gcd(N a, N b) {
  return b ? gcd(b, a % b) : a;
}
inline void gn(long long& x) {
  int sg = 1;
  char c;
  while (((c = getchar()) < '0' || c > '9') && c != '-')
    ;
  c == '-' ? (sg = -1, x = 0) : (x = c - '0');
  while ((c = getchar()) >= '0' && c <= '9') x = x * 10 + c - '0';
  x *= sg;
}
inline void gn(int& x) {
  long long t;
  gn(t);
  x = t;
}
inline void gn(unsigned long long& x) {
  long long t;
  gn(t);
  x = t;
}
inline void gn(double& x) {
  double t;
  scanf("%lf", &t);
  x = t;
}
inline void gn(long double& x) {
  double t;
  scanf("%lf", &t);
  x = t;
}
inline long long sqr(long long a) { return a * a; }
inline double sqrf(double a) { return a * a; }
int inf = 0x3f3f3f3f;
double eps = 1e-6;
int mo = 1000000007;
int qp(int a, long long b) {
  int n = 1;
  do {
    if (b & 1) n = 1ll * n * a % mo;
    a = 1ll * a * a % mo;
  } while (b >>= 1);
  return n;
}
namespace sat {
const int SAT_MAXV = 300000 + 5;
const int SAT_MAXE = 300000 + 5;
struct edge {
  int v, next;
} e[SAT_MAXE * 4];
int g[SAT_MAXV * 2], etot;
int vtot;
void ae(int u, int v) {
  e[etot].v = v;
  e[etot].next = g[u];
  g[u] = etot++;
  upmax(vtot, (max(u, v) + 1) >> 1);
}
int dfn[SAT_MAXV * 2], low[SAT_MAXV * 2], stk[SAT_MAXV * 2];
bool inst[SAT_MAXV * 2];
int ind, top, scctot, sccid[SAT_MAXV * 2], seq[SAT_MAXV * 2], seqtot;
int tmpans[SAT_MAXV * 2], ans[SAT_MAXV];
void dfs(int u) {
  dfn[u] = low[u] = ++ind;
  inst[stk[++top] = u] = 1;
  for (int i = g[u]; ~i; i = e[i].next)
    if (!dfn[e[i].v]) {
      dfs(e[i].v);
      low[u] = min(low[u], low[e[i].v]);
    } else if (inst[e[i].v])
      low[u] = min(low[u], dfn[e[i].v]);
  if (low[u] == dfn[u]) {
    ++scctot;
    while (1) {
      bool bo = stk[top] == u;
      seq[++seqtot] = stk[top];
      sccid[stk[top]] = scctot;
      inst[stk[top--]] = 0;
      if (bo) break;
    }
  }
}
void dfs2(int u) {
  tmpans[u] = 1;
  for (int i = g[u]; ~i; i = e[i].next)
    if (!~tmpans[e[i].v]) dfs2(e[i].v);
}
bool sat() {
  for (int i = (1), _ed = (2 * vtot + 1); i < _ed; i++)
    if (!dfn[i]) dfs(i);
  for (int i = (1), _ed = (vtot + 1); i < _ed; i++)
    if (sccid[2 * i - 1] == sccid[2 * i]) return 0;
  return 1;
}
void getsol() {
  for (int i = (1), _ed = (2 * vtot + 1); i < _ed; i++) tmpans[i] = -1;
  for (int i = (2 * vtot + 1) - 1, _ed = (1); i >= _ed; i--) {
    int u = seq[i];
    if (!~tmpans[u]) {
      tmpans[u] = 0;
      if (u & 1)
        u++;
      else
        u--;
      dfs2(u);
    }
  }
  for (int i = (1), _ed = (vtot + 1); i < _ed; i++) ans[i] = tmpans[i * 2 - 1];
}
void make(int i, bool v) {
  if (v)
    ae(i * 2, i * 2 - 1);
  else
    ae(i * 2 - 1, i * 2);
}
void makenot(int i, bool v, int j, bool w) {
  ae(i * 2 - v, j * 2 - (!w)), ae(j * 2 - w, i * 2 - (!v));
}
void makeand(int i, int j, bool v) {
  if (v)
    make(i, 1), make(j, 1);
  else
    makenot(i, 1, j, 1);
}
void makeor(int i, int j, bool v) {
  if (!v)
    make(i, 0), make(j, 0);
  else
    makenot(i, 0, j, 0);
}
void makexor(int i, int j, bool v) {
  if (v)
    makenot(i, 0, j, 0), makenot(i, 1, j, 1);
  else
    makenot(i, 1, j, 0), makenot(i, 0, j, 1);
}
void sat_init() {
  static bool ini = 0;
  if (!ini) {
    ini = 1;
    memset(g, -1, sizeof(g));
  } else {
    for (int i = 0; i <= 2 * vtot; i++)
      g[i] = -1, dfn[i] = low[i] = sccid[i] = 0;
  }
  vtot = etot = scctot = ind = seqtot = 0;
}
};  // namespace sat
vector<int> ad[55555];
int n, m;
struct edge {
  int u, v, c, t, id;
} e[55555];
map<int, int> ma;
int check(int T) {
  int ndtot = m;
  sat::sat_init();
  for (int u = 1; u <= n; u++) {
    int bo = 0;
    ma.clear();
    for (int i = 0; i < ((int)(ad[u]).size()); i++) {
      int id = ad[u][i];
      if (ma[e[id].c]) {
        if (bo) return 0;
        bo = e[id].c;
      }
      ma[e[id].c]++;
    }
    if (bo) {
      int x = 0, y = 0;
      for (int i = (0), _ed = (((int)(ad[u]).size())); i < _ed; i++) {
        int id = ad[u][i];
        if (e[id].c != bo)
          sat::make(id, 0);
        else {
          if (x == 0)
            x = id;
          else
            y = id;
        }
      }
      sat::makexor(x, y, 1);
    } else {
      for (int i = (0), _ed = (((int)(ad[u]).size())); i < _ed; i++) {
        int id = ad[u][i];
        sat::makenot(id, 1, ndtot + i + 1, 0);
        if (i) {
          sat::makenot(ndtot + i + 1 - 1, 1, ndtot + i + 1, 0);
          sat::makeand(ndtot + i + 1 - 1, id, 0);
        }
      }
      ndtot += ((int)(ad[u]).size());
    }
  }
  for (int i = (1), _ed = (m + 1); i < _ed; i++)
    if (e[i].t > T) sat::make(i, 0);
  return sat::sat();
}
int main() {
  gn(n);
  gn(m);
  for (int i = (1), _ed = (m + 1); i < _ed; i++) {
    int u, v, c, t;
    gn(u);
    gn(v);
    gn(c);
    gn(t);
    e[i] = (edge){u, v, c, t, i};
    ad[u].push_back(i);
    ad[v].push_back(i);
  }
  if (!check(2e9)) {
    printf("No\n");
  } else {
    int l = 0, r = 1e9, mid;
    while (l <= r) {
      mid = l + r >> 1;
      if (check(mid))
        r = mid - 1;
      else
        l = mid + 1;
    }
    check(l);
    sat::getsol();
    int su = 0;
    for (int i = (1), _ed = (m + 1); i < _ed; i++)
      if (sat::ans[i]) su++;
    printf("Yes\n%d %d\n", l, su);
    for (int i = (1), _ed = (m + 1); i < _ed; i++)
      if (sat::ans[i]) printf("%d ", i);
  }
  return 0;
}
