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 std::vector;
template <typename Tp>
Tp Max(const Tp &a, const Tp &b) {
  return a > b ? a : b;
}
template <typename Tp>
Tp Min(const Tp &a, const Tp &b) {
  return a < b ? a : b;
}
template <typename Tp>
void Read(Tp &x) {
  Tp in = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    in = in * 10 + ch - '0';
    ch = getchar();
  }
  x = in * f;
}
const int SN = (50000 + 10) << 1;
const int SM = SN << 2;
struct Edge {
  int v, next;
} E1[SM], E2[SM];
struct EDGE {
  int u, v, c, t, num, cnt;
} a[SN];
bool cmp(EDGE a, EDGE b) { return a.c < b.c; }
int head1[SN], hashs[SN], head2[SN], vis[SN], num1, num2, n, m;
vector<int> b[SN / 2], Ans;
int pre[SN], net[SN];
void Add1(int u, int v) {
  E1[++num1].v = v, E1[num1].next = head1[u], head1[u] = num1;
}
void Add2(int u, int v) {
  E2[++num2].v = v, E2[num2].next = head2[u], head2[u] = num2;
}
namespace Tarjan {
int LOW[SN], DFN[SN], sta[SN], in[SN], bel[SN], opp[SN], top, tot, TIME, node;
void Clear() {
  memset(bel, 0, sizeof bel);
  memset(head1, 0, sizeof head1);
  memset(LOW, 0, sizeof LOW);
  memset(DFN, 0, sizeof DFN);
  memset(in, 0, sizeof in);
  top = tot = TIME = node = num1 = 0;
}
void tarjan(int u) {
  in[u] = 1, LOW[u] = DFN[u] = ++TIME, sta[++top] = u;
  for (int i = head1[u]; i; i = E1[i].next) {
    int to = E1[i].v;
    if (!DFN[to])
      tarjan(to), LOW[u] = Min(LOW[u], LOW[to]);
    else if (in[to])
      LOW[u] = Min(LOW[u], DFN[to]);
  }
  if (DFN[u] == LOW[u]) {
    bel[u] = ++tot, in[u] = 0;
    while (sta[top] != u) in[sta[top]] = 0, bel[sta[top--]] = tot;
    top--;
  }
}
}  // namespace Tarjan
using namespace Tarjan;
bool Judge(int mid) {
  Clear();
  node = (m << 1) - 1;
  for (int i = 1; i <= n; i++) b[i].clear();
  for (int i = 1; i <= m; i++)
    b[a[i].u].push_back(a[i].num), b[a[i].v].push_back(a[i].num);
  for (int i = 1; i <= n; i++) {
    int limits = b[i].size();
    if (limits == 0 || limits == 1) continue;
    for (int j = 0; j < limits; j++)
      if (a[b[i][j]].t > mid) Add1((b[i][j] - 1) << 1, (b[i][j] - 1) << 1 | 1);
    for (int j = 0; j < limits; j++) {
      pre[j] = ++node;
      if (j != 0) Add1(pre[j], pre[j - 1]);
      Add1(pre[j], (b[i][j] - 1) << 1 | 1);
    }
    for (int j = limits - 1; j >= 0; j--) {
      net[j] = ++node;
      if (j != limits - 1) Add1(net[j], net[j + 1]);
      Add1(net[j], (b[i][j] - 1) << 1 | 1);
    }
    for (int j = 0; j < limits; j++) {
      if (j != 0) Add1((b[i][j] - 1) << 1, pre[j - 1]);
      if (j != limits - 1) Add1((b[i][j] - 1) << 1, net[j + 1]);
    }
  }
  for (int i = 1; i <= n; i++) b[i].clear();
  int point = 1;
  for (int i = 1; i <= m; i = point) {
    while (a[point].c == a[i].c && point <= m) {
      b[a[point].u].push_back(a[point].num),
          b[a[point].v].push_back(a[point].num);
      point++;
    }
    for (int now = 1; now <= n; now++) {
      if (b[now].size() == 0 || b[now].size() == 1) continue;
      int limits = b[now].size();
      for (int j = 0; j < limits; j++) {
        pre[j] = ++node;
        if (j != 0) Add1(pre[j], pre[j - 1]);
        Add1(pre[j], (b[now][j] - 1) << 1);
      }
      for (int j = limits - 1; j >= 0; j--) {
        net[j] = ++node;
        if (j != limits - 1) Add1(net[j], net[j + 1]);
        Add1(net[j], (b[now][j] - 1) << 1);
      }
      for (int j = 0; j < limits; j++) {
        if (j != 0) Add1((b[now][j] - 1) << 1 | 1, pre[j - 1]);
        if (j != limits - 1) Add1((b[now][j] - 1) << 1 | 1, net[j + 1]);
      }
    }
    for (int k = i; k <= point - 1; k++) b[a[k].u].clear(), b[a[k].v].clear();
  }
  for (int i = 0; i <= node; i++)
    if (!DFN[i]) tarjan(i);
  int flag = 0;
  for (int i = 1; i <= m; i++)
    if (bel[(i - 1) << 1] == bel[(i - 1) << 1 | 1]) {
      flag = 1;
      break;
    }
  return flag ^ 1;
}
void print() {
  memset(in, 0, sizeof in);
  top = 0;
  for (int i = 0; i < (m << 1); i++) {
    for (int j = head1[i]; j; j = E1[j].next) {
      int to = E1[j].v;
      if (bel[to] != bel[i]) Add2(bel[to], bel[i]), in[bel[i]]++;
    }
    opp[bel[i]] = bel[i ^ 1];
  }
  for (int i = 1; i <= tot; i++)
    if (!in[i]) sta[++top] = i;
  while (top) {
    int now = sta[top--];
    if (!vis[now]) vis[now] = 1, vis[opp[now]] = 2;
    for (int i = head2[now]; i; i = E2[i].next) {
      int to = E2[i].v;
      if (!(--in[to])) sta[++top] = to;
    }
  }
  putchar(10);
  for (int i = 1; i <= m; i++) {
    printf("%d %d\n", vis[bel[(i - 1) << 1]], vis[bel[(i - 1) << 1 | 1]]);
    if (vis[bel[(i - 1) << 1]] == 1 && vis[bel[(i - 1) << 1 | 1]] == 2)
      Ans.push_back(a[i].cnt);
  }
  int res = Ans.size();
  printf("%d\n", res);
  for (int i = 0; i < res; i++) printf("%d ", Ans[i]);
  putchar(10);
}
int main() {
  Read(n), Read(m);
  node = (m << 1) - 1;
  for (int i = 1; i <= m; i++) {
    Read(a[i].u), Read(a[i].v), Read(a[i].c), Read(a[i].t);
    hashs[++hashs[0]] = a[i].c, a[i].cnt = i;
  }
  std::sort(hashs + 1, hashs + hashs[0] + 1);
  hashs[0] = std::unique(hashs + 1, hashs + hashs[0] + 1) - hashs - 1;
  for (int i = 1; i <= m; i++)
    a[i].c = std::lower_bound(hashs + 1, hashs + hashs[0] + 1, a[i].c) - hashs;
  hashs[0] = 0;
  for (int i = 1; i <= m; i++) hashs[++hashs[0]] = a[i].t;
  std::sort(hashs + 1, hashs + hashs[0] + 1);
  hashs[0] = std::unique(hashs + 1, hashs + hashs[0] + 1) - hashs - 1;
  std::sort(a + 1, a + m + 1, cmp);
  for (int i = 1; i <= m; i++) a[i].num = i;
  int l = 1, r = hashs[0], ans = 0;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (Judge(hashs[mid]))
      ans = mid, r = mid - 1;
    else
      l = mid + 1;
  }
  if (ans == 0) puts("No"), exit(0);
  puts("Yes");
  Judge(hashs[ans]);
  printf("%d ", hashs[ans]);
  for (int i = 1; i <= m; i++)
    if (bel[(i - 1) << 1] < bel[(i - 1) << 1 | 1]) Ans.push_back(a[i].cnt);
  int res = Ans.size();
  printf("%d\n", res);
  for (int i = 0; i < res; i++) printf("%d ", Ans[i]);
  return 0;
}
