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.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.io.InputStream;
import java.io.BufferedReader;
import java.util.Map;
import java.util.List;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.HashMap;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.Arrays;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author AlexFetisov
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD_CF_XXX solver = new TaskD_CF_XXX();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD_CF_XXX {
        private int m;
        private int n;
        private int[][] edgesForVertex;
        TaskD_CF_XXX.Edge[] edges;
        List<Integer>[] g;

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            n = in.nextInt();
            m = in.nextInt();
            edges = new TaskD_CF_XXX.Edge[m];
            g = new List[n];
            for (int i = 0; i < n; ++i) {
                g[i] = new ArrayList<Integer>();
            }
            int maxPrice = 0;
            for (int i = 0; i < m; ++i) {
                edges[i] = new TaskD_CF_XXX.Edge(in.nextInt() - 1, in.nextInt() - 1, in.nextInt(), in.nextInt(), i);
                g[edges[i].a].add(i);
                g[edges[i].b].add(i);
                maxPrice = Math.max(maxPrice, edges[i].price);
            }
            edgesForVertex = new int[2][n];
            int left = 0, right = maxPrice;
            int resPrice = -1;
            while (left <= right) {
                int middle = (left + right) / 2;
                if (tryPrice(middle)) {
                    resPrice = middle;
                    right = middle - 1;
                } else {
                    left = middle + 1;
                }
            }
            if (resPrice == -1) {
                out.println("No");
                return;
            }
            out.println("Yes");
            tryPrice(resPrice);

            int amRoads = 0;
            for (TaskD_CF_XXX.Edge e : edges) {
                if (e.removed) {
                    ++amRoads;
                }
            }
            out.println(resPrice + " " + amRoads);
            for (TaskD_CF_XXX.Edge e : edges) {
                if (e.removed) {
                    out.print(e.id + 1);
                    out.print(" ");
                }
            }
            out.println();
        }

        private boolean tryPrice(int price) {
            ArrayUtils.fill(edgesForVertex, -1);
            for (int v = 0; v < n; ++v) {
                Map<Integer, List<Integer>> colors = new HashMap<Integer, List<Integer>>();
                for (int eId : g[v]) {
                    if (!addColorToMap(colors, edges[eId])) {
                        return false;
                    }
                }
                int am = 0;
                for (List<Integer> list : colors.values()) {
                    if (list.size() == 2) {
                        edgesForVertex[0][v] = list.get(0);
                        edgesForVertex[1][v] = list.get(1);
                        ++am;
                        if (am == 2) return false;
                    }
                }
            }

            Solver2SAT solver2SAT = new Solver2SAT(4 * m, 10 * m, 2 * m);
            for (TaskD_CF_XXX.Edge e : edges) {
                e.removed = false;
                if (e.price > price) {
                    solver2SAT.fixVariable(e.id);
                }
            }
            for (int v = 0; v < n; ++v) {
                if (edgesForVertex[1][v] != -1) {
                    solver2SAT.addOr(edgesForVertex[0][v], edgesForVertex[1][v]);
                }
                for (int ei = 0; ei < g[v].size(); ++ei) {
                    solver2SAT.addOr(solver2SAT.non(g[v].get(ei)), m + g[v].get(ei));
                    if (ei > 0) {
                        solver2SAT.addOr(solver2SAT.non(m + g[v].get(ei - 1)), m + g[v].get(ei));
                    }
                    if (ei < g[v].size() - 1) {
                        solver2SAT.addOr(solver2SAT.non(m + g[v].get(ei)), solver2SAT.non(g[v].get(ei + 1)));
                    }
                }
            }

            int[] components = solver2SAT.run();
            for (int i = 0; i < m; ++i) {
                if (components[i] == components[solver2SAT.non(i)]) return false;
                if (components[i + m] == components[solver2SAT.non(i + m)]) return false;
                if (components[i] > components[solver2SAT.non(i)]) {
                    edges[i].removed = true;
                }
            }
            for (int v = 0; v < n; ++v) {
                HashSet<Integer> colorIt = new HashSet<Integer>();
                for (int eid : g[v]) {
                    if (edges[eid].removed) continue;
                    int c = edges[eid].color;
                    if (colorIt.contains(c)) {
                        return false;
                    }
                    colorIt.add(c);
                }
            }
            return true;
        }

        private boolean addColorToMap(Map<Integer, List<Integer>> dict, TaskD_CF_XXX.Edge e) {
            List<Integer> ids;
            if (!dict.containsKey(e.color)) {
                ids = new ArrayList<Integer>();
            } else {
                ids = dict.get(e.color);
            }
            if (ids.size() == 2) return false;
            ids.add(e.id);
            dict.put(e.color, ids);
            return true;
        }

        class Edge {
            int a;
            int b;
            int color;
            int id;
            int price;
            boolean removed;

            public Edge(int a, int b, int color, int price, int id) {
                this.a = a;
                this.b = b;
                this.color = color;
                this.price = price;
                removed = false;
                this.id = id;
            }

        }

    }

    static class StrongComponents {
        static int[] colors;
        static List<Integer> order;
        static Graph g;
        static Graph gr;

        public static int[] run(int n, Graph ig, Graph igr) {
            g = ig;
            gr = igr;
            colors = new int[n];
            order = new ArrayList<Integer>(n);
            for (int i = 0; i < n; ++i) {
                if (colors[i] == 0) {
                    dfs1(i);
                }
            }
            Arrays.fill(colors, -1);
            int nextColor = 0;
            for (int i = 0; i < n; ++i) {
                int v = order.get(n - 1 - i);
                if (colors[v] == -1) {
                    dfs2(v, nextColor++);
                }
            }
            return colors;
        }

        private static void dfs1(int v) {
            colors[v] = 1;
            for (int i = g.first[v]; i != -1; i = g.next[i]) {
                if (colors[g.to[i]] == 0) {
                    dfs1(g.to[i]);
                }
            }
            order.add(v);
        }

        private static void dfs2(int v, int color) {
            colors[v] = color;
            for (int i = gr.first[v]; i != -1; i = gr.next[i]) {
                if (colors[gr.to[i]] == -1) {
                    dfs2(gr.to[i], color);
                }
            }
        }

        public static int[] run(Graph g) {
            Graph ig = new Graph();
            ig.initGraph(g.nVertex, g.nEdges);
            for (int v = 0; v < g.nVertex; ++v) {
                for (int e = g.first[v]; e != -1; e = g.next[e]) {
                    int to = g.to[e];
                    ig.addDirectEdge(to, v);
                }
            }
            return run(g.nVertex, g, ig);
        }

    }

    static class Graph {
        public int[] from;
        public int[] to;
        public int[] first;
        public int[] next;
        public int nVertex;
        public int nEdges;
        public int curEdge;

        public Graph() {
        }

        public void initGraph(int n, int m) {
            curEdge = 0;
            nVertex = n;
            nEdges = m;
            from = new int[m * 2];
            to = new int[m * 2];
            first = new int[n];
            next = new int[m * 2];
            Arrays.fill(first, -1);
        }

        public void addDirectEdge(int a, int b) {
            next[curEdge] = first[a];
            first[a] = curEdge;
            to[curEdge] = b;
            from[curEdge] = a;
            ++curEdge;
        }

    }

    static class Solver2SAT {
        Graph g;
        int size;

        public Solver2SAT(int n, int m, int size) {
            g = new Graph();
            g.initGraph(n, m);
            this.size = size;
        }

        public int non(int x) {
            return x < size ? x + size : x - size;
        }

        public void addOr(int from, int to) {
            addImply(non(from), to);
            addImply(non(to), from);
        }

        public void fixVariable(int x) {
            addImply(x, non(x));
        }

        public void addImply(int from, int to) {
            g.addDirectEdge(from, to);
        }

        public int[] run() {
            return StrongComponents.run(g);
        }

    }

    static class InputReader {
        private BufferedReader reader;
        private StringTokenizer stt;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream));
        }

        public String nextLine() {
            try {
                return reader.readLine();
            } catch (IOException e) {
                return null;
            }
        }

        public String nextString() {
            while (stt == null || !stt.hasMoreTokens()) {
                stt = new StringTokenizer(nextLine());
            }
            return stt.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(nextString());
        }

    }

    static class ArrayUtils {
        public static void fill(int[][] f, int value) {
            for (int i = 0; i < f.length; ++i) {
                Arrays.fill(f[i], value);
            }
        }

    }
}

