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


// In the name of god

#pragma GCC optimize("O2")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> 
#include <ext/pb_ds/tree_policy.hpp> 

using namespace std;
using namespace __gnu_pbds; 

template < class T > using ordered_set = tree < T , null_type , less < T > , rb_tree_tag , tree_order_statistics_node_update >;
  
typedef long long                   ll;
typedef long double                 ld;
typedef pair<int,int>               pii;
typedef pair<ll,ll>                 pll;
#define all(x)                      (x).begin(),(x).end()
#define lc(x)                       (x) << 1
#define rc(x)                       (x) << 1 | 1
#define F                           first
#define S                           second
#define fast_io                     ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define file_io                     freopen("in.txt" , "r+" , stdin) ; freopen("out.txt" , "w+" , stdout);
ll poww(ll a, ll b, ll md) {
    ll ans = 1;
    for(; b; b >>= 1, a = a * a % md){
        if(b & 1){
            ans = ans * a % md;
        }
    }
    return ans % md;
}
struct ed{
    int v;int u; int c; int t; int ind;
};

const int MAXN = 5e5 + 10;
const int MAXLG = 18;
const int MOD = 1e9 + 7;
const int MOD2 = 998244353;
const ll INF = 8e18;
int n, m, cnt, colo, val[MAXN], col[MAXN], vlc[MAXN];
ed edge[MAXN];
vector<int> adj[MAXN], in[MAXN], out[MAXN], topol, ans;
bool mark[MAXN];

bool cmp(ed a, ed b){
    return (a.t < b.t);
}

bool cmp2(int a, int b){
    return (edge[a].c < edge[b].c);
}

void add_edge(int v, int u){
    out[v].push_back(u);
    in[u].push_back(v);
}

void add_val(int v, int u){
    add_edge(v ^ 1, u);
    add_edge(u ^ 1, v);
}

void dfs(int v){
    mark[v] = true;
    for(auto u : out[v]){
        if(mark[u]){
            continue;
        }
        dfs(u);
    }
    topol.push_back(v);
}

void sfd(int v){
    mark[v] = true;
    col[v] = colo;
    for(auto u : in[v]){
        if(mark[u]){
            continue;
        }
        sfd(u);
    }
}

void preprocess(){
    for(int i = 0; i < n; i++){
        for(int j = 1; j < (int)adj[i].size(); j++){
            int tmp = adj[i][j];
            int pmt = adj[i][j - 1];
            if(edge[tmp].c == edge[pmt].c){
                add_val(lc(tmp), lc(pmt));
                add_val(rc(tmp), rc(pmt));
            }
        }
    }

    cnt = m;
    for(int i = 0; i < n; i++){
        int tmp, pmt;
        if(!(int)adj[i].size()){
            continue;
        }
        tmp = adj[i][0];
        add_val(rc(tmp), lc(cnt));
        cnt++;
        for(int j = 1; j < (int)adj[i].size(); j++){
            tmp = adj[i][j];
            pmt = adj[i][j - 1];
            add_val(rc(tmp), rc(pmt));
            add_val(rc(tmp), lc(cnt));
            add_val(rc(cnt - 1), lc(cnt));
            add_val(rc(cnt - 1), rc(tmp));
            cnt++;
        }
    }

    for(int i = 0; i < lc(cnt); i++){
        if(mark[i]){
            continue;
        }
        dfs(i);
    }

    reverse(all(topol));
    memset(mark, 0, sizeof mark);
    for(auto v : topol){
        if(mark[v]){
            continue;
        }
        sfd(v);
        colo++;
    }
}

bool dfs2(int v){
    mark[v] = true;
    if(vlc[col[v]] == 0){
        return false;
    }
    vlc[col[v]] = 1;
    for(auto u : out[v]){
        if(mark[u]){
            continue;
        }
        if(dfs2(u) == false){
            return false;
        }
    }
    return true;
}

bool dfs3(int v){
    mark[v] = true;
    if(vlc[col[v]] == 1){
        return false;
    }
    vlc[col[v]] = 0;
    for(auto u : in[v]){
        if(mark[u]){
            continue;
        }
        if(dfs3(u) == false){
            return false;
        }
    }
    return true;
}

bool solve(int v, int p){
    if(vlc[col[v]] != -1){
        return (vlc[col[v]] == p);
    }
    if(p == 0){
        return dfs3(v);
    }
    return dfs2(v);
}

bool check(int x){
    memset(val, -1, sizeof val);
    memset(vlc, -1, sizeof vlc);
    memset(mark, 0, sizeof mark);
    int q = 0;
    for(int i = 0; i < m; i++){
        if(edge[i].t <= x){
            q++;
        }
        else{
            break;
        }
    }

    for(int i = q; i < m; i++){
        if(col[lc(i)] == col[rc(i)]){
            return false;
        }
        val[lc(i)] = 0;
        val[rc(i)] = 1;
        if(!solve(lc(i), 0)){
            return false;
        }
        if(!solve(rc(i), 1)){
            return false;
        }
    }
    for(int i = 0; i < q; i++){
        if(col[lc(i)] == col[rc(i)]){
            return false;
        }
        if(vlc[col[lc(i)]] != -1){
            val[lc(i)] = vlc[col[lc(i)]];
            val[rc(i)] = val[lc(i)] ^ 1;
            if(!solve(lc(i), val[lc(i)])){
                return false;
            }
            if(!solve(rc(i), val[rc(i)])){
                return false;
            }
            continue;
        }
        if(vlc[col[rc(i)]] != -1){
            val[rc(i)] = vlc[col[rc(i)]];
            val[lc(i)] = val[rc(i)] ^ 1;
            if(!solve(rc(i), val[rc(i)])){
                return false;
            }
            if(!solve(lc(i), val[lc(i)])){
                return false;
            }
            continue;
        }
        val[lc(i)] = (col[lc(i)] > col[rc(i)]);
        val[rc(i)] = val[lc(i)] ^ 1;
        solve(lc(i), val[lc(i)]);
        solve(rc(i), val[rc(i)]);
    }
    return true;
}

int main()
{
    scanf("%d %d", &n, &m);
    for(int i = 0; i < m; i++){
        scanf("%d %d %d %d", &edge[i].v, &edge[i].u, &edge[i].c, &edge[i].t);
        edge[i].v--;
        edge[i].u--;
        edge[i].ind = i;
    }
    sort(edge, edge + m, cmp);
    
    for(int i = 0; i < m; i++){
        adj[edge[i].v].push_back(i);
        adj[edge[i].u].push_back(i);
    }
    for(int i = 0; i < n; i++){
        sort(all(adj[i]), cmp2);
    }

    preprocess();

    int l, r, mid;
    l = 0;
    r = 1000 * 1000 * 1000 + 1;
    while(r - l > 1){
        mid = (l + r) / 2;
        if(check(mid)){
            r = mid;
        }
        else{
            l = mid;
        }
    }
    if(r == 1000 * 1000 * 1000 + 1){
        printf("No\n");
        return 0;
    }
    r = max(r, 1);
    check(r);
    int k = 0;
    for(int i = 0; i < m; i++){
        if(val[lc(i)]){
            ans.push_back(edge[i].ind);
            k++;
        }
    }
    sort(all(ans));
    printf("Yes\n");
    printf("%d %d\n", r, k);
    for(int i = 0; i < (int)ans.size();i++){
        printf("%d ", ans[i] + 1);
    }
    printf("\n");
}


