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


import java.util.*;
import java.io.*;
import static java.lang.System.*;
import static java.lang.Integer.*;

public class CF587D{
	public static ArrayList<Node> nodes = new ArrayList<Node>();
	public static ArrayList<Edge> edges = new ArrayList<Edge>();
	public static ArrayList<Edge> ans = new ArrayList<Edge>();
	
	public static boolean setEdge(Edge e){
		e.st = 1;
		ArrayList<Edge> aadj = e.a.adj.get(e.c);
		ArrayList<Edge> badj = e.b.adj.get(e.c);
		for(Edge e2: aadj){
			if(e2 == e) continue;
			if(e2.st == -1) continue;
			if(e2.st == 1 || e2.a.rem || e2.b.rem){
				return false;
			}else{
				e2.st = -1;
				e2.p = e.a;
				ans.add(e2);
				e2.a.rem = true;
				e2.b.rem = true;
			}
		}
		for(Edge e2: badj){
			if(e2 == e) continue;
			if(e2.st == -1) continue;
			if(e2.st == 1 || e2.a.rem || e2.b.rem){
				return false;
			}else{
				e2.st = -1;
				e2.p = e.b;
				ans.add(e2);
				e2.a.rem = true;
				e2.b.rem = true;
			}
		}
		return true;
	}
	
	public static boolean checkMatches(){
		for(int i=0; i<nodes.size(); i++){
			for(ArrayList<Edge> adj: nodes.get(i).adj.values()){
				if(adj.size() > 1){
					if(!setEdge(adj.get(0))) return false;
				};
			}
		}
		return true;
	}
	
	public static boolean check(int t){
		ans = new ArrayList<Edge>();
		int index = Collections.binarySearch(edges, new Edge(null, null, -1, t, -1));
		if(index < 0){
			index = -(index+1);
		}
		for(int i=0; i<nodes.size(); i++){
			nodes.get(i).rem = false;
		}
		for(int i=0; i<edges.size(); i++){
			edges.get(i).st = 0;
		}
		while(index < edges.size()-1 && edges.get(index+1).t <= t) index++;
		if(index < edges.size() && edges.get(index).t <= t) index++;
		if(index == edges.size()){
			return checkMatches();
		}
		for(int i=index; i<edges.size(); i++){
			// out.println("	Setting Edge " + edges.get(i).id + "(" + edges.get(i).a.id + "," + edges.get(i).b.id + ")");
			if(!setEdge(edges.get(i))){
				// out.println("	Unable to set Edge " + edges.get(i).id + "(" + edges.get(i).a.id + "," + edges.get(i).b.id + ")");
				return false;
			}
		}
		for(int i=0; i<ans.size(); i++){
			if(ans.get(i).p != ans.get(i).a){
				ArrayList<Edge> adj = ans.get(i).a.madj;
				for(Edge e: adj){
					if(e == ans.get(i) || e.st == 1) continue;
					if(e.st == -1) return false;
					if(!setEdge(e)) return false;
				}
			}
			if(ans.get(i).p != ans.get(i).b){
				ArrayList<Edge> adj = ans.get(i).b.madj;
				for(Edge e: adj){
					if(e == ans.get(i) || e.st == 1) continue;
					if(e.st == -1) return false;
					if(!setEdge(e)) return false;
				}
			}
		}
		return true;
	}
	
	public static void main(String[] args) throws Exception{
		BufferedReader sc = new BufferedReader(new InputStreamReader(in));
		StringTokenizer st = new StringTokenizer(sc.readLine());
		
		int n = parseInt(st.nextToken());
		int m = parseInt(st.nextToken());
		
		for(int i=0; i<n; i++){
			nodes.add(new Node(i+1));
		}
		int maxt = 0;
		for(int i=0; i<m; i++){
			st = new StringTokenizer(sc.readLine());
			Node a = nodes.get(parseInt(st.nextToken())-1);
			Node b = nodes.get(parseInt(st.nextToken())-1);
			int c = parseInt(st.nextToken());
			int t = parseInt(st.nextToken());
			Edge e = new Edge(a, b, c, t, i+1);
			edges.add(e);
			a.addEdge(e);
			b.addEdge(e);
			maxt = Math.max(maxt, t);
		}
		
		Collections.sort(edges);
		int L = 0;
		int R = maxt;
		while(R-L > 3){
			int M = (L+R)/2;
			// out.println("Checking " + M);
			if(check(M)){
				R = M;
				// out.println("	Yes");
			}else{
				L = M;
				// out.println("	No");
			}
		}
		boolean done = false;
		while(L <= R && !done){
			// out.println("Checking " + L);
			if(check(L)){
				StringBuilder sb = new StringBuilder();
				sb.append("Yes\n");
				int max = 0;
				for(int i=0; i<ans.size(); i++){
					max = Math.max(max, ans.get(i).t);
				}
				sb.append(max + " " + ans.size() + "\n");
				for(int i=0; i<ans.size(); i++){
					if(i != 0) sb.append(" ");
					sb.append(ans.get(i).id);
				}
				sb.append("\n");
				out.print(sb.toString());
				done = true;
				break;
			}
			L++;
		}
		if(!done){
			out.println("No");
		}
	}
}

class Node{
	ArrayList<Edge> madj = new ArrayList<Edge>();
	HashMap<Integer, ArrayList<Edge> > adj = new HashMap<Integer, ArrayList<Edge> >();
	int id;
	boolean rem;
	public Node(int n){
		id = n;
	}
	public void addEdge(Edge e){
		madj.add(e);
		if(adj.containsKey(e.c)){
			adj.get(e.c).add(e);
		}else{
			ArrayList<Edge> list = new ArrayList<Edge>();
			list.add(e);
			adj.put(e.c, list);
		}
	}
}

class Edge implements Comparable<Edge>{
	Node a, b, p;
	int c, t, id, st;
	public Edge(Node a, Node b, int c, int d, int n){
		this.a = a;
		this.b = b;
		this.c = c;
		t = d;
		id = n;
	}
	public int compareTo(Edge e){
		return t - e.t;
	}
}