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;
const int maxn = 50000 + 1000;
const int maxv = maxn * 6;
const int maxm = maxv * 8;
const int inf = 1000000000 + 10;
struct edgekind {
  int u, v, c, t;
} edge[maxn];
vector<pair<int, int> > adj[maxn];
int n, m, nvtx, pj[maxv];
int tot, V[maxm], N[maxm], F[maxm];
int top, col, NUM, dfn[maxv], low[maxv], q[maxv], bel[maxv], stk[maxv],
    deg[maxv];
bool instk[maxv];
vector<int> inedge[maxv];
bool cho[maxv];
void Input() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d%d%d", &edge[i].u, &edge[i].v, &edge[i].c, &edge[i].t);
    adj[edge[i].u].push_back(make_pair(edge[i].c, i));
    adj[edge[i].v].push_back(make_pair(edge[i].c, i));
  }
  for (int i = 1; i <= n; i++) sort(adj[i].begin(), adj[i].end());
  for (int i = 1; i <= n; i++) {
    for (int l = 0; l < (int)adj[i].size(); l++) {
      int r = l;
      while (r + 1 < (int)adj[i].size() &&
             adj[i][l].first == adj[i][r + 1].first)
        r++;
      if (r - l + 1 >= 3) {
        printf("No\n");
        exit(0);
      }
      l = r;
    }
  }
}
int num(int x, int k) { return x * 2 - 1 + k; }
void add(int a, int b) { ++tot, V[tot] = b, N[tot] = F[a], F[a] = tot; }
void build(int ans) {
  for (int i = 1; i <= m; i++)
    if (edge[i].t > ans) add(num(i, 1), num(i, 0));
  for (int i = 1; i <= n; i++) {
    for (int l = 0; l < (int)adj[i].size(); l++) {
      int r = l;
      while (r + 1 < (int)adj[i].size() &&
             adj[i][l].first == adj[i][r + 1].first)
        r++;
      if (l != r) {
        add(num(adj[i][l].second, 0), num(adj[i][r].second, 1));
        add(num(adj[i][r].second, 0), num(adj[i][l].second, 1));
      }
      l = r;
    }
  }
  for (int i = 1; i <= n; i++) {
    int k = (int)adj[i].size();
    for (int j = 0; j < k; j++) pj[j] = nvtx + j + 1;
    for (int j = 1; j < k; j++) {
      add(num(pj[j - 1], 1), num(pj[j], 1));
      add(num(pj[j], 0), num(pj[j - 1], 0));
    }
    for (int j = 0; j < k; j++) {
      add(num(adj[i][j].second, 1), num(pj[j], 1));
      add(num(pj[j], 0), num(adj[i][j].second, 0));
    }
    for (int j = 0; j + 1 < k; j++) {
      add(num(pj[j], 1), num(adj[i][j + 1].second, 0));
      add(num(adj[i][j + 1].second, 1), num(pj[j], 0));
    }
    nvtx += k;
  }
}
void tarjan(int x) {
  dfn[x] = low[x] = ++NUM;
  instk[x] = true;
  stk[++top] = x;
  for (int p = F[x]; p > 0; p = N[p]) {
    int y = V[p];
    if (!dfn[y])
      tarjan(y), low[x] = min(low[x], low[y]);
    else if (instk[y])
      low[x] = min(low[x], dfn[y]);
  }
  if (dfn[x] == low[x]) {
    ++col;
    int y;
    do {
      y = stk[top];
      instk[y] = false;
      bel[y] = col;
      top--;
    } while (y != x);
  }
}
bool check(int ans) {
  memset(F, 0, sizeof F);
  memset(N, 0, sizeof N);
  tot = 0;
  nvtx = m;
  build(ans);
  memset(dfn, 0, sizeof dfn);
  top = NUM = col = 0;
  for (int i = 1; i <= 2 * nvtx; i++)
    if (!dfn[i]) tarjan(i);
  for (int i = 1; i <= nvtx; i++) {
    if (bel[num(i, 0)] == bel[num(i, 1)]) {
      return false;
    }
  }
  return true;
}
vector<int> has[maxv], prt;
bool getval[maxv];
void spread(int x) {
  if (getval[(x + 1) / 2]) return;
  getval[(x + 1) / 2] = true;
  if (x % 2 == 0 && (x + 1) / 2 <= m) prt.push_back((x + 1) / 2);
  for (int p = F[x]; p > 0; p = N[p]) spread(V[p]);
}
void out(int ans) {
  check(ans);
  int hd = 0, tl = 0;
  for (int i = 1; i <= 2 * nvtx; i++) inedge[i].clear();
  memset(deg, 0, sizeof deg);
  for (int i = 1; i <= 2 * nvtx; i++)
    for (int p = F[i]; p > 0; p = N[p]) {
      int x = bel[i], y = bel[V[p]];
      if (x != y) {
        inedge[y].push_back(x);
        deg[x]++;
      }
    }
  for (int i = 1; i <= col; i++)
    if (deg[i] == 0) q[++tl] = i;
  while (hd != tl) {
    int x = q[++hd];
    for (int y : inedge[x]) {
      if ((--deg[y]) == 0) q[++tl] = y;
    }
  }
  for (int i = 1; i <= col; i++) has[i].clear();
  for (int i = 1; i <= 2 * nvtx; i++) {
    has[bel[i]].push_back(i);
  }
  memset(getval, 0, sizeof getval);
  prt.clear();
  for (int i = 1; i <= tl; i++) {
    int x = q[i];
    for (int e : has[i]) {
      if (!getval[(e + 1) / 2]) {
        spread(e);
      }
    }
  }
  sort(prt.begin(), prt.end());
  printf("%d %d\n", ans, (int)prt.size());
  for (int e : prt) printf("%d ", e);
  printf("\n");
}
void Solve() {
  int l = 0, r = inf;
  if (!check(r)) {
    printf("No\n");
    exit(0);
  }
  while (l <= r) {
    if (check(((l + r) >> 1)))
      r = ((l + r) >> 1) - 1;
    else
      l = ((l + r) >> 1) + 1;
  }
  int ans = r + 1;
  printf("Yes\n");
  out(ans);
}
int main() {
  Input();
  Solve();
  return 0;
}
