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 N = 100005;
int n, m, componentsNo;
int from[N], to[N], color[N], destructTime[N];
int edge[N], component[N], state[N];
bool vis[N];
vector<int> G[N];
vector<pair<int, int> > V[N];
bool cmp(int a, int b) { return destructTime[a] < destructTime[b]; }
bool cmp2(const pair<int, int> &a, const pair<int, int> &b) {
  return color[a.second] < color[b.second];
}
void DFS(int w) {
  component[w] = componentsNo;
  vis[w] = true;
  for (int i = 0; i < G[w].size(); i++) {
    int u = G[w][i];
    if (!vis[u]) {
      DFS(u);
    }
  }
}
bool good(int w) {
  for (int i = 1; i <= componentsNo; i++) {
    state[i] = 0;
  }
  for (int i = 1; i <= n; i++) {
    int last = -1;
    int lastId = -1;
    for (int j = 0; j < V[i].size(); j++) {
      int col = color[V[i][j].second];
      if (col != last) {
        last = col;
        lastId = V[i][j].second;
      } else {
        for (int k = 0; k < V[i].size(); k++) {
          int x = V[i][k].second;
          if (x != V[i][j].second && x != lastId) {
            if (state[component[2 * x]] == -1) {
              return false;
            }
            state[component[2 * x]] = 1;
            state[component[2 * x + 1]] = -1;
          }
        }
      }
    }
  }
  for (int i = m; i > w; i--) {
    if (state[component[2 * edge[i]]] == -1) {
      return false;
    }
    state[component[2 * edge[i]]] = 1;
    state[component[2 * edge[i] + 1]] = -1;
  }
  for (int i = 1; i <= n; i++) {
    int last = -1;
    int lastId = -1;
    bool found = false;
    for (int j = 0; j < V[i].size(); j++) {
      int col = color[V[i][j].second];
      if (col != last) {
        last = col;
        lastId = V[i][j].second;
      } else {
        found = true;
        break;
      }
      if (state[component[2 * V[i][j].second]] == -1) {
        for (int k = 0; k < V[i].size(); k++) {
          int x = V[i][k].second;
          if (x != V[i][j].second) {
            if (state[component[2 * x]] == -1) {
              return false;
            }
            state[component[2 * x]] = 1;
            state[component[2 * x + 1]] = -1;
          }
        }
        found = true;
        break;
      }
    }
    if (!found) {
      for (int k = 0; k < V[i].size(); k++) {
        int x = V[i][k].second;
        state[component[2 * x]] = 1;
        state[component[2 * x + 1]] = -1;
      }
    }
  }
  for (int i = 2; i <= 2 * m + 1; i += 2) {
    if (state[component[i]] == 0) {
      state[component[i]] = 1;
      state[component[i ^ 1]] = -1;
    }
  }
  for (int i = 2; i <= 2 * m + 1; i += 2) {
    if (state[component[i]] == 0) {
      state[component[i]] = 1;
      state[component[i ^ 1]] = -1;
    }
  }
  return true;
}
int main() {
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= m; i++) {
    scanf("%d %d %d %d", &from[i], &to[i], &color[i], &destructTime[i]);
    V[from[i]].push_back({to[i], i});
    V[to[i]].push_back({from[i], i});
    edge[i] = i;
  }
  sort(edge + 1, edge + 1 + m, cmp);
  for (int i = 1; i <= n; i++) {
    sort(V[i].begin(), V[i].end(), cmp2);
    int last = -1;
    int lastId = -1;
    int cnt = 0;
    for (int j = 0; j < V[i].size(); j++) {
      int col = color[V[i][j].second];
      if (col != last) {
        last = col;
        lastId = V[i][j].second;
      } else {
        cnt++;
        G[2 * V[i][j].second].push_back(2 * lastId + 1);
        G[2 * lastId].push_back(2 * V[i][j].second + 1);
        G[2 * lastId + 1].push_back(2 * V[i][j].second);
        G[2 * V[i][j].second + 1].push_back(2 * lastId);
      }
      if (cnt > 1) {
        printf("No\n");
        return 0;
      }
    }
  }
  for (int i = 2; i <= 2 * m + 1; i++) {
    if (!vis[i]) {
      componentsNo++;
      DFS(i);
    }
  }
  for (int i = 2; i <= 2 * m + 1; i++) {
    if (component[i] == component[i ^ 1]) {
      printf("No\n");
      return 0;
    }
  }
  int low = 0;
  int high = m;
  int ret = m + 1;
  while (low <= high) {
    int mid = (low + high) / 2;
    if (good(mid)) {
      ret = mid;
      high = mid - 1;
    } else {
      low = mid + 1;
    }
  }
  if (ret == m + 1) {
    printf("No\n");
    return 0;
  }
  good(ret);
  vector<int> edges;
  for (int i = 1; i <= m; i++) {
    if (state[component[2 * i]] == -1) {
      edges.push_back(i);
    }
  }
  printf("Yes\n");
  printf("%d %d\n", destructTime[edge[ret]], edges.size());
  for (int i = 0; i < edges.size(); i++) {
    printf("%d ", edges[i]);
  }
  return 0;
}
