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>
#pragma GCC optimize("Ofast")
const int P = 1e9 + 7;
using namespace std;
template <typename T>
inline void ckmax(T &a, T b) {
  (a < b) && (a = b);
}
template <typename T>
inline void ckmin(T &a, T b) {
  (a > b) && (a = b);
}
inline int mul(int a, int b) { return 1ll * a * b % P; }
inline int add(int a, int b) { return a + b >= P ? a + b - P : a + b; }
inline int sub(int a, int b) { return a - b >= 0 ? a - b : a - b + P; }
inline void mulmod(int &a, int b) { a = mul(a, b); }
inline void addmod(int &a, int b) { ((a += b) >= P) && (a -= P); }
inline void submod(int &a, int b) { ((a -= b) < 0) && (a += P); }
inline int ksm(int a, int b) {
  int ans = 1;
  for (; b; b >>= 1) {
    if (b & 1) ans = 1ll * ans * a % P;
    a = 1ll * a * a % P;
  }
  return ans;
}
inline int inv(int a) { return ksm(a, P - 2); }
namespace FastIO {
const int SIZE = 1 << 16;
char buf[SIZE], obuf[SIZE], str[64];
int bi = SIZE, bn = SIZE, opt;
int read(char *s) {
  while (bn) {
    for (; bi < bn && buf[bi] <= ' '; bi++)
      ;
    if (bi < bn) break;
    bn = fread(buf, 1, SIZE, stdin), bi = 0;
  }
  int sn = 0;
  while (bn) {
    for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
    if (bi < bn) break;
    bn = fread(buf, 1, SIZE, stdin), bi = 0;
  }
  s[sn] = 0;
  return sn;
}
bool read(int &x) {
  if (x) x = 0;
  int bf = 0, n = read(str);
  if (!n) return 0;
  int i = 0;
  if (str[i] == '-') bf = 1, i = 1;
  for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
  if (bf) x = -x;
  return 1;
}
void write(int x) {
  if (!x)
    obuf[opt++] = '0';
  else {
    if (x < 0) obuf[opt++] = '-', x = -x;
    int sn = 0;
    while (x) str[sn++] = x % 10 + '0', x /= 10;
    for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
  }
  if (opt >= (SIZE >> 1)) {
    fwrite(obuf, 1, opt, stdout);
    opt = 0;
  }
}
void write(char x) {
  obuf[opt++] = x;
  if (opt >= (SIZE >> 1)) {
    fwrite(obuf, 1, opt, stdout);
    opt = 0;
  }
}
void Fflush() {
  if (opt) fwrite(obuf, 1, opt, stdout);
  opt = 0;
}
};  // namespace FastIO
inline int read() {
  int x;
  FastIO::read(x);
  return x;
}
const int MN = 1e5 + 5;
int n, m;
struct Edge {
  int u, v, c, t, id;
  bool operator<(const Edge &b) const { return t < b.t; }
} e[MN];
vector<int> C[MN], G[MN];
namespace Graph {
const int N = MN * 10;
vector<int> e[N];
int scc_cnt, dfn[N], low[N], ins[N], s[N], top, ind, col[N], n;
void addedge(int u, int v) { e[u].push_back(v); }
void init(int tn) {
  n = tn, scc_cnt = 0, ind = 0, scc_cnt = 0;
  assert(top == 0);
  for (int i = (1); i <= (n); i++)
    dfn[i] = low[i] = ins[i] = col[i] = 0, e[i].clear();
}
void tarjan(int u) {
  dfn[u] = low[u] = ++ind;
  ins[s[++top] = u] = 1;
  for (auto v : e[u]) {
    if (!dfn[v]) {
      tarjan(v);
      ckmin(low[u], low[v]);
    } else if (ins[v])
      ckmin(low[u], low[v]);
  }
  if (low[u] == dfn[u]) {
    ++scc_cnt;
    while (s[top] != u) {
      ins[s[top]] = 0;
      col[s[top--]] = scc_cnt;
    }
    assert(s[top] == u);
    ins[s[top]] = 0;
    col[s[top--]] = scc_cnt;
  }
}
void solve() {
  for (int i = (1); i <= (n); i++) {
    if (!dfn[i]) tarjan(i);
  }
}
}  // namespace Graph
bool cmp(int i, int j) { return e[i].c < e[j].c; }
set<int> s[MN];
bool check(int mid) {
  fprintf(stderr, "check %d:\n", mid);
  Graph::init(6 * mid);
  for (int i = (1); i <= (mid); i++)
    Graph::addedge(i, i + mid), Graph::addedge(i + 2 * mid, i + 3 * mid),
        Graph::addedge(i + 3 * mid, i + 4 * mid),
        Graph::addedge(i + 5 * mid, i);
  for (int i = (1); i <= (n); i++) C[i].clear(), G[i].clear(), s[i].clear();
  for (int i = (1); i <= (mid); i++)
    C[e[i].u].push_back(i), C[e[i].v].push_back(i);
  for (int i = (mid + 1); i <= (m); i++)
    G[e[i].u].push_back(i), G[e[i].v].push_back(i);
  for (int i = (1); i <= (n); i++)
    sort(G[i].begin(), G[i].end(), cmp), sort(C[i].begin(), C[i].end(), cmp);
  for (int i = (1); i <= (n); i++) {
    int lst = 0;
    for (auto id : G[i]) {
      if (lst && e[id].c == e[lst].c) {
        return 0;
      }
      s[i].insert(e[id].c);
      lst = id;
    }
  }
  for (int i = (1); i <= (n); i++) {
    int lst = 0;
    for (auto id : C[i]) {
      if (s[i].count(e[id].c)) Graph::addedge(id + 3 * mid, id);
      if (!lst) {
        lst = id;
        continue;
      }
      Graph::addedge(id + mid, lst + 3 * mid);
      Graph::addedge(lst, id + 2 * mid);
      Graph::addedge(lst + 2 * mid, id + 2 * mid);
      Graph::addedge(id + mid, lst + mid);
      lst = id;
    }
  }
  for (int i = (1); i <= (n); i++) {
    int lst = 0;
    for (auto id : C[i]) {
      if (!lst || e[id].c != e[lst].c) {
        lst = id;
        continue;
      }
      Graph::addedge(id + 4 * mid, lst);
      Graph::addedge(lst + 3 * mid, id + 5 * mid);
      Graph::addedge(id + 4 * mid, lst + 4 * mid);
      Graph::addedge(lst + 5 * mid, id + 5 * mid);
      lst = id;
    }
  }
  cerr << "?";
  Graph::solve();
  cerr << "?";
  for (int i = (1); i <= (mid); i++) {
    if (Graph::col[i] == Graph::col[i + 3 * mid]) return 0;
  }
  return 1;
}
signed main() {
  n = read(), m = read();
  for (int i = (1); i <= (m); i++) {
    e[i].u = read(), e[i].v = read(), e[i].c = read(), e[i].t = read(),
    e[i].id = i;
  }
  sort(e + 1, e + 1 + m);
  int l = 0, r = m, ans = -1;
  while (l <= r) {
    int mid = (l + r) >> 1;
    if (check(mid))
      r = mid - 1, ans = mid;
    else
      l = mid + 1;
  }
  if (ans == -1)
    printf("No\n");
  else {
    check(ans);
    vector<int> res;
    printf("Yes\n");
    for (int i = (1); i <= (ans); i++) {
      if (Graph::col[i] < Graph::col[i + 3 * ans]) {
        res.push_back(i);
      }
    }
    printf("%d %d\n", e[ans].t, (int)res.size());
    for (auto it : res) {
      printf("%d ", e[it].id);
    }
    printf("\n");
  }
  return FastIO::Fflush(), 0;
}
