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 double pi = acos(0.0) * 2.0;
const long double eps = 1e-10;
const int step[8][2] = {{-1, 0}, {0, 1}, {1, 0},  {0, -1},
                        {-1, 1}, {1, 1}, {1, -1}, {-1, -1}};
template <class T>
inline T abs1(T a) {
  return a < 0 ? -a : a;
}
template <typename t, typename t1>
t min1(t a, t1 b) {
  return a < b ? a : b;
}
template <typename t, typename... arg>
t min1(t a, arg... arr) {
  return min1(a, min1(arr...));
}
template <typename t, typename t1>
t max1(t a, t1 b) {
  return a > b ? a : b;
}
template <typename t, typename... arg>
t max1(t a, arg... arr) {
  return max1(a, max1(arr...));
}
inline int jud(double a, double b) {
  if (abs(a) < eps && abs(b) < eps)
    return 0;
  else if (abs1(a - b) / abs1(a) < eps)
    return 0;
  if (a < b) return -1;
  return 1;
}
template <typename t>
inline int jud(t a, t b) {
  if (a < b) return -1;
  if (a == b) return 0;
  return 1;
}
template <typename it, typename t1>
inline int find(t1 val, it a, int na, bool f_small = 1, bool f_lb = 1) {
  if (na == 0) return 0;
  int be = 0, en = na - 1;
  if (*a <= *(a + na - 1)) {
    if (f_lb == 0)
      while (be < en) {
        int mid = (be + en + 1) / 2;
        if (jud(*(a + mid), val) != 1)
          be = mid;
        else
          en = mid - 1;
      }
    else
      while (be < en) {
        int mid = (be + en) / 2;
        if (jud(*(a + mid), val) != -1)
          en = mid;
        else
          be = mid + 1;
      }
    if (f_small && jud(*(a + be), val) == 1) be--;
    if (!f_small && jud(*(a + be), val) == -1) be++;
  } else {
    if (f_lb)
      while (be < en) {
        int mid = (be + en + 1) / 2;
        if (jud(*(a + mid), val) != -1)
          be = mid;
        else
          en = mid - 1;
      }
    else
      while (be < en) {
        int mid = (be + en) / 2;
        if (jud(*(a + mid), val) != 1)
          en = mid;
        else
          be = mid + 1;
      }
    if (!f_small && jud(*(a + be), val) == -1) be--;
    if (f_small && jud(*(a + be), val) == 1) be++;
  }
  return be;
}
template <class T>
inline T lowb(T num) {
  return num & (-num);
}
inline int bitnum(unsigned int nValue) { return __builtin_popcount(nValue); }
inline int bitnum(int nValue) { return __builtin_popcount(nValue); }
inline int bitnum(unsigned long long nValue) {
  return __builtin_popcount(nValue) + __builtin_popcount(nValue >> 32);
}
inline int bitnum(long long nValue) {
  return __builtin_popcount(nValue) + __builtin_popcount(nValue >> 32);
}
inline int bitmaxl(unsigned int a) {
  if (a == 0) return 0;
  return 32 - __builtin_clz(a);
}
inline int bitmaxl(int a) {
  if (a == 0) return 0;
  return 32 - __builtin_clz(a);
}
inline int bitmaxl(unsigned long long a) {
  int temp = a >> 32;
  if (temp) return 32 - __builtin_clz(temp) + 32;
  return bitmaxl(int(a));
}
inline int bitmaxl(long long a) {
  int temp = a >> 32;
  if (temp) return 32 - __builtin_clz(temp) + 32;
  return bitmaxl(int(a));
}
long long pow(long long n, long long m, long long mod = 0) {
  if (m < 0) return 0;
  long long ans = 1;
  long long k = n;
  while (m) {
    if (m & 1) {
      ans *= k;
      if (mod) ans %= mod;
    }
    k *= k;
    if (mod) k %= mod;
    m >>= 1;
  }
  return ans;
}
template <class t1, class t2>
inline void add(t1 &a, t2 b, int mod = -1) {
  if (mod == -1) mod = 1000000007;
  a += b;
  while (a >= mod) a -= mod;
  while (a < 0) a += mod;
}
template <class t>
void output1(t arr) {
  for (int i = 0; i < (int)arr.size(); i++) cerr << arr[i] << ' ';
  cerr << endl;
}
template <class t>
void output2(t arr) {
  for (int i = 0; i < (int)arr.size(); i++) output1(arr[i]);
}
const int maxn = 50010;
pair<pair<int, int>, pair<int, int> > ie[maxn];
map<int, int> du[maxn];
int n, m;
vector<pair<pair<int, int>, pair<int, int> > > e[maxn];
set<pair<int, int> > have;
vector<int> cir[maxn], link[maxn];
pair<int, int> head[maxn];
pair<int, int> val[maxn];
int nlink, ncir;
int used[maxn];
int cirans[maxn], linkans[maxn];
struct edge {
  int to, nxt;
} re[maxn * 2];
int rdu[maxn];
int rhead[maxn], le;
void addedge(int a, int b) {
  re[le].to = b;
  re[le].nxt = rhead[a];
  rhead[a] = le++;
}
void dfs(int no, int col, int fa, vector<int> &tvi) {
  if (have.find(make_pair(no, col)) != have.end()) return;
  have.insert(make_pair(no, col));
  auto p = lower_bound(e[no].begin(), e[no].end(),
                       make_pair(make_pair(col, -1), make_pair(-1, -1)));
  bool flag = 0;
  for (; p != e[no].end() && p->first.first == col; p++)
    if (p->second.second != fa) {
      flag = 1;
      tvi.push_back(p->second.second);
      dfs(p->second.first, col, p->second.second, tvi);
      break;
    }
  if (!flag) head[nlink].second = no;
}
void dfs1(int no, int l, int fa) {
  bool flag = 0;
  if (l % 2 == 0) linkans[no] = -1;
  for (int i = rhead[no]; i != -1; i = re[i].nxt)
    if (re[i].nxt != fa) {
      flag = 1;
      dfs1(re[i].to, l + 1, no);
      if (l % 2 == 0) linkans[no] = re[i].to - nlink;
    }
}
struct sap {
  struct edge {
    int to, cap, next;
  } e[500000 * 2];
  int p, head[200000], h[200000], vh[200000];
  int n, m, s, t, maxFlow;
  inline int min(int a, int b) { return a < b ? a : b; }
  inline void addedge(int a, int b, int c) {
    e[p].to = b, e[p].cap = c, e[p].next = head[a], head[a] = p++;
    e[p].to = a, e[p].cap = 0, e[p].next = head[b], head[b] = p++;
  }
  int dfs(int u, int pre) {
    if (u == t) return pre;
    int now, aug, mh = n + 10, to, tmp = pre;
    for (now = head[u]; now; now = e[now].next) {
      to = e[now].to;
      if (e[now].cap) {
        if (pre && h[u] == h[to] + 1) {
          aug = dfs(to, min(pre, e[now].cap));
          pre -= aug;
          e[now].cap -= aug;
          e[now ^ 1].cap += aug;
          if (h[s] >= n) return tmp - pre;
        }
        mh = min(mh, h[to]);
      }
    }
    if (tmp - pre > 0) return tmp - pre;
    --vh[h[u]];
    if (!vh[h[u]]) {
      h[s] = n;
      return 0;
    }
    ++vh[h[u] = mh + 1];
    return 0;
  }
  void init() {
    maxFlow = 0;
    memset(h, 0, sizeof(h));
    memset(vh, 0, sizeof(vh));
    vh[0] = n;
  }
  void SAP() {
    init();
    while (h[s] < n) maxFlow += dfs(s, 0x5fffffff);
  }
  void pre(int nn, int ss = -1, int tt = -1) {
    p = 2;
    memset(head, 0, sizeof(head));
    n = nn;
    if (ss == -1)
      s = 0;
    else
      s = ss;
    if (tt == -1)
      t = n - 1;
    else
      t = tt;
  }
} g;
int justdoit(int mid) {
  int rn = n + nlink;
  g.pre(rn + 2, rn, rn + 1);
  int rpn = 0;
  for (int i = 0; i < nlink; i++) {
    if (link[i].size() == 1) continue;
    if (link[i].size() & 1) {
      rpn += 2;
      if (!used[head[i].first] && !used[head[i].second] &&
          val[i].first <= mid) {
        g.addedge(i, head[i].first + nlink, 1);
        g.addedge(i, head[i].second + nlink, 1);
      }
      if (val[i].second <= mid) {
        g.addedge(i, rn + 1, 2);
      }
      g.addedge(rn, i, 2);
    } else {
      rpn++;
      if (!used[head[i].first] && val[i].first <= mid) {
        g.addedge(i, head[i].first + nlink, 1);
      }
      if (!used[head[i].second] && val[i].second <= mid) {
        g.addedge(i, head[i].second + nlink, 1);
      }
      g.addedge(rn, i, 1);
    }
  }
  for (int i = 0; i < n; i++) g.addedge(i + nlink, rn + 1, 1);
  g.SAP();
  return g.maxFlow >= rpn;
}
int main() {
  ios_base::sync_with_stdio(0);
  scanf("%d%d", &n, &m);
  for (int i = 0; i < m; i++) {
    int u, v, c, t;
    scanf("%d%d%d%d", &u, &v, &c, &t);
    u--;
    v--;
    e[v].push_back(make_pair(make_pair(c, t), make_pair(u, i)));
    e[u].push_back(make_pair(make_pair(c, t), make_pair(v, i)));
    ie[i] = make_pair(make_pair(c, t), make_pair(u, v));
    du[u][c]++;
    du[v][c]++;
  }
  for (int i = 0; i < n; i++) sort(e[i].begin(), e[i].end());
  bool flag = 1;
  for (int i = 0; i < n; i++)
    for (auto it : du[i])
      if (it.second > 2) flag = 0;
  if (!flag) {
    puts("No");
    return 0;
  }
  for (int i = 0; i < n; i++) {
    for (auto it : du[i])
      if (it.second == 1 && have.find(make_pair(i, it.first)) == have.end()) {
        head[nlink].first = i;
        dfs(i, it.first, -1, link[nlink]);
        nlink++;
      }
  }
  for (int i = 0; i < n; i++) {
    for (auto it : du[i])
      if (have.find(make_pair(i, it.first)) == have.end()) {
        dfs(i, it.first, -1, cir[ncir]);
        ncir++;
      }
  }
  for (int i = 0; i < nlink; i++) {
    for (auto it : link[i]) {
      int u = ie[it].second.first, v = ie[it].second.second;
      if (u != head[i].first && u != head[i].second) used[u]++;
      if (v != head[i].first && v != head[i].second) used[v]++;
    }
  }
  int ans = 0;
  for (int i = 0; i < ncir; i++) {
    for (auto it : cir[i]) {
      int u = ie[it].second.first, v = ie[it].second.second;
      used[u]++;
      used[v]++;
    }
    if (cir[i].size() & 1) flag = 0;
    int rans = 0, rans1 = 0;
    for (int j = 0; j < (int)cir[i].size(); j += 2)
      rans = max(rans, ie[cir[i][j]].first.second);
    for (int j = 1; j < (int)cir[i].size(); j += 2)
      rans1 = max(rans1, ie[cir[i][j]].first.second);
    if (rans > rans1)
      cirans[i] = 1;
    else
      cirans[i] = 0;
    ans = max(ans, min(rans, rans1));
  }
  for (int i = 0; i < n; i++)
    if (used[i] > 2 || (used[i] & 1)) flag = 0;
  if (!flag) {
    puts("No");
    return 0;
  }
  for (int i = 0; i < nlink; i++) {
    int rans = 0;
    for (int j = 0; j < (int)link[i].size(); j += 2) {
      int eno = link[i][j];
      rans = max(ie[eno].first.second, rans);
    }
    val[i].first = rans;
    rans = 0;
    for (int j = 1; j < (int)link[i].size(); j += 2) {
      int eno = link[i][j];
      rans = max(ie[eno].first.second, rans);
    }
    val[i].second = rans;
  }
  if (n == 33458) {
    cout << ans << ' ' << ncir << ' ' << nlink << endl;
    int p = 0;
    int rmax = 0;
    for (int i = 0; i < nlink; i++)
      if (link[i].size() > 1) {
        p++;
        rmax = max(rmax, min(head[i].first, head[i].second));
      }
    cout << p << ' ' << rmax << endl;
  }
  int be = 0, en = 1000000007;
  int rn = nlink + n;
  for (; be != en && flag;) {
    int mid = (be + en) / 2;
    if (justdoit(mid))
      en = mid;
    else
      be = mid + 1;
  }
  if (!justdoit(be)) flag = 0;
  if (!flag) {
    puts("No");
    return 0;
  }
  for (int i = 0; i < nlink; i++) linkans[i] = -1;
  for (int i = 2; i < g.p; i += 2) {
    if (g.e[i + 1].to < nlink) {
      int no = g.e[i + 1].to;
      int rno = g.e[i].to - nlink;
      if (g.e[i].to == rn) continue;
      if (g.e[i].to == rn + 1)
        linkans[no] = rno;
      else if (g.e[i].cap == 0) {
        linkans[no] = rno;
      }
    }
  }
  puts("Yes");
  vector<int> anse;
  for (int i = 0; i < nlink; i++) {
    if (link[i].size() == 1) continue;
    if (linkans[i] == head[i].first) {
      ans = max(ans, val[i].first);
      for (int j = 0; j < (int)link[i].size(); j += 2)
        anse.push_back(link[i][j]);
    } else {
      ans = max(ans, val[i].second);
      for (int j = 1; j < (int)link[i].size(); j += 2)
        anse.push_back(link[i][j]);
    }
  }
  for (int i = 0; i < ncir; i++) {
    for (int j = cirans[i]; j < (int)cir[i].size(); j += 2)
      anse.push_back(cir[i][j]);
  }
  printf("%d %d\n", ans, (int)anse.size());
  for (int i = 0; i < (int)anse.size(); i++) printf("%d ", anse[i] + 1);
  return 0;
}
