#include <bits/stdc++.h>
using namespace std;
const int MX = 50005;
const int INF = 1111111111;
int C[MX], Cn;
vector<int> conV[MX];
struct Edge {
  int id;
  int u, v, c, t;
  void in() {
    scanf("%d%d%d%d", &u, &v, &c, &t);
    u--, v--;
    conV[u].push_back(id);
    conV[v].push_back(id);
    C[Cn++] = c;
  }
} edge[MX];
int N, M;
vector<int> con[6 * MX], rcon[6 * MX], gcon[6 * MX];
int group[6 * MX], vis[6 * MX], Gn;
int Not(int u) { return (u + 3 * MX) % (6 * MX); }
void add(int u, int v) {
  con[u].push_back(v);
  con[Not(v)].push_back(Not(u));
  rcon[v].push_back(u);
  rcon[Not(u)].push_back(Not(v));
}
bool preprocess() {
  int frq[MX] = {0}, ege[MX], egn;
  int newV = MX;
  for (int i = 0; i < N; i++) {
    egn = 0;
    for (auto it : conV[i]) {
      if (frq[edge[it].c] == i + 1) ege[egn++] = it;
      frq[edge[it].c] = i + 1;
    }
    if (egn > 1) return false;
    if (egn)
      for (auto it : conV[i])
        if (it != ege[0] && edge[it].c == edge[ege[0]].c) ege[egn++] = it;
    assert(egn == 0 || egn == 2);
    if (egn) {
      add(ege[0], Not(ege[1]));
      add(Not(ege[0]), ege[1]);
    }
    int ii = 0, sz = conV[i].size();
    for (auto it : conV[i]) {
      add(it, newV);
      if (ii < sz - 1) {
        add(newV, newV + 1);
      }
      if (ii) {
        add(it, Not(newV - 1));
      }
      ii++, newV++;
    }
  }
  return true;
}
int que[6 * MX], qn;
void dfs(int u) {
  vis[u] = true;
  for (auto it : con[u])
    if (!vis[it]) dfs(it);
  que[qn++] = u;
}
void DFS(int u) {
  vis[u] = true;
  group[u] = Gn;
  for (auto it : rcon[u])
    if (!vis[it]) DFS(it);
}
void SCC() {
  for (int i = 0; i < 6 * MX; i++)
    if (!vis[i]) dfs(i);
  for (int i = 0; i < 6 * MX; i++) vis[i] = 0;
  for (int i = qn - 1; i >= 0; i--)
    if (!vis[que[i]]) Gn++, DFS(que[i]);
}
int val[6 * MX], gval[6 * MX];
bool gdfs(int u) {
  vis[u] = 1;
  if (gval[u] != -1) {
    if (!gval[u])
      return false;
    else
      return true;
  }
  gval[u] = 1;
  for (auto it : gcon[u]) {
    if (!gdfs(it)) return false;
  }
  return true;
}
bool can(int Max) {
  for (int i = 0; i < 6 * MX; i++) val[i] = gval[i] = -1, vis[i] = 0;
  for (int i = 1; i <= M; i++)
    if (edge[i].t > Max) {
      if (gval[group[i]] != -1) {
        if (gval[group[i]] == 1)
          return false;
        else
          continue;
      }
      gval[group[i]] = 0;
      if (!gdfs(group[Not(i)])) return false;
    }
  return true;
}
bool process() {
  SCC();
  for (int i = 0; i < 6 * MX; i++)
    if (group[i] == group[Not(i)]) {
      return false;
    }
  for (int i = 0; i < 6 * MX; i++) {
    for (auto it : con[i]) {
      if (group[i] == group[it]) continue;
      gcon[group[i]].push_back(group[it]);
    }
  }
  int st = 0, en = INF;
  for (int it = 0; it < 50; it++) {
    int md = st + en >> 1;
    if (can(md))
      en = md;
    else
      st = md;
  }
  can(en);
  for (int i = 1; i <= M; i++) {
    if (gval[group[i]] != -1)
      val[i] = gval[group[i]];
    else {
      if (gval[group[Not(i)]] != -1)
        val[i] = !gval[group[Not(i)]];
      else {
        int u = group[i], v = group[Not(i)];
        val[i] = gval[u] = u > v, gval[v] = v > u;
      }
    }
  }
  int cnt = 0;
  for (int i = 1; i <= M; i++) cnt += val[i];
  puts("Yes");
  printf("%d %d\n", en, cnt);
  int flg = 0;
  for (int i = 1; i <= M; i++)
    if (val[i]) {
      if (!flg)
        flg = 1;
      else
        putchar(' ');
      printf("%d", i);
    }
  puts("");
  return true;
}
int main() {
  scanf("%d%d", &N, &M);
  for (int i = 0; i < MX; i++) edge[i].id = i;
  for (int i = 1; i <= M; i++) edge[i].in();
  sort(C, C + Cn);
  Cn = unique(C, C + Cn) - C;
  for (int i = 1; i <= M; i++)
    edge[i].c = lower_bound(C, C + Cn, edge[i].c) - C;
  if (!preprocess()) {
    puts("No");
    return 0;
  }
  if (!process()) {
    puts("No");
    return 0;
  }
  return 0;
}
