import java.io.*;
import java.util.*;

public class TaskD {
    private final InputReader reader;
    private final OutputWriter writer;

    public TaskD(InputReader reader, OutputWriter writer) {
        this.reader = reader;
        this.writer = writer;
    }

    public static void main(String[] args) throws FileNotFoundException {
        //InputReader reader = new InputReader(new FileInputStream("/home/lafa/input-10.txt"));
        InputReader reader = new InputReader(System.in);
        //OutputWriter writer = new OutputWriter(new FileOutputStream("/home/lafa/log1"));
        OutputWriter writer = new OutputWriter(System.out);
        new TaskD(reader, writer).run();
        writer.writer.flush();
    }

    int[] A, B, C, T;

    List<Integer>[] E;
    List<Integer>[] F, RF;

    int n, m;

    int[] topsort;
    int tpt;

    int[] temp2 = new int[2];

    int iter;
    int[] was;

    void DFS(int x) {
        was[x] = iter;
        for (int y : F[x]) {
            if (was[y] != iter)
                DFS(y);
        }
        topsort[tpt++] = x;
    }

    int[] col;
    void DFS2(int x, int c) {
        was[x] = iter;
        col[x] = c;
        for (int y : RF[x]) {
            if (was[y] != iter)
                DFS2(y, c);
        }
    }

    ArrayList<Integer> enabled = new ArrayList<Integer>();

    boolean can(int v) {
        iter++;
        for (int i = 0; i < m; i++) {
            if (T[i] > v) {
                F[2 * i + 1].add(2 * i);
                RF[2 * i].add(2 * i + 1);
            }
        }

        tpt = 0;
        for (int x = 0; x < 6 * m; x++) {
            if (was[x] != iter) {
                DFS(x);
            }
        }

        if (tpt != 6 * m)
            throw new AssertionError();
        int cur_col = 0;
        iter++;
        for (int i = tpt - 1; i >= 0; i--) {
            int x = topsort[i];
            if (was[x] != iter)
                DFS2(x, cur_col++);
        }
        enabled.clear();

        boolean bad = false;
        for (int i = 0; i < m; i++) {
            if (col[2 * i] == col[2 * i + 1])
                bad = true;
            if (col[2 * i + 1] > col[2 * i])
                enabled.add(i);
        }

        for (int i = 0; i < m; i++) {
            if (T[i] > v) {
                F[2 * i + 1].remove(F[2 * i + 1].size() - 1);
                RF[2 * i].remove(RF[2 * i].size() - 1);
            }
        }
        return !bad;
    }

    final int inf = 1000 * 1000 * 1000 + 42;

    int[] prv, nxt;

    int get_orient(int i, int e) {
        return (A[e] == i) ? 2 * e : 2 * e + 1;
    }

    public void run() {
        n = reader.nextInt();
        m = reader.nextInt();
        A = new int[m];
        B = new int[m];
        C = new int[m];
        T = new int[m];
        E = new ArrayList[n];
        for (int i = 0; i < n; i++)
            E[i] = new ArrayList<Integer>();
        for (int i = 0; i < m; i++) {
            A[i] = reader.nextInt() - 1;
            B[i] = reader.nextInt() - 1;
            C[i] = reader.nextInt();
            T[i] = reader.nextInt();
            E[A[i]].add(i);
            E[B[i]].add(i);
        }
        F = new List[6 * m];
        RF = new List[6 * m];
        for (int i = 0; i < 6 * m; i++) {
            F[i] = new ArrayList<Integer>();
            RF[i] = new ArrayList<Integer>();
        }
        was = new int[6 * m];
        topsort = new int[6 * m];
        prv = new int[2 * m];
        nxt = new int[2 * m];
        Arrays.fill(prv, -1);
        Arrays.fill(nxt, -1);
        for (int x = 0; x < n; x++) {
            Collections.sort(E[x], new Comparator<Integer>() {
                @Override
                public int compare(Integer a, Integer b) {
                    return Integer.compare(C[a], C[b]);
                }
            });
            int ea = -1, eb = -1;
            for (int l = 0, r = 0; l < E[x].size(); l = r) {
                while (r != E[x].size() && C[E[x].get(r)] == C[E[x].get(l)])
                    r++;
                if (r - l == 1)
                    continue;
                if (r - l > 2 || ea != -1) {
                    writer.printf("No\n");
                    return;
                }
                ea = E[x].get(l);
                eb = E[x].get(l + 1);
                F[2 * ea].add(2 * eb + 1);
                RF[2 * eb + 1].add(2 * ea);
                F[2 * eb].add(2 * ea + 1);
                RF[2 * ea + 1].add(2 * eb);
            }
        }
        for (int i = 0; i < n; i++) {
            for (int e : E[i]) {
                e = get_orient(i, e);
                prv[e] = nxt[e] = -1;
            }
            for (int j = 0; j < E[i].size() - 1; j++) {
                int e = E[i].get(j);
                int f = E[i].get(j + 1);
                e = get_orient(i, e);
                f = get_orient(i, f);
                prv[f] = e;
                nxt[e] = f;
            }
            for (int e : E[i]) {
                e = get_orient(i, e);
                F[2 * m + 2 * e + 0].add(2 * (e / 2) + 0);
                F[2 * m + 2 * e + 1].add(2 * (e / 2) + 0);
                RF[2 * (e / 2) + 0].add(2 * m + 2 * e + 0);
                RF[2 * (e / 2) + 0].add(2 * m + 2 * e + 1);

                if (prv[e] != -1) {
                    F[2 * m + 2 * e + 0].add(2 * m + 2 * prv[e] + 0);
                    RF[2 * m + 2 * prv[e] + 0].add(2 * m + 2 * e + 0);
                    F[2 * (e / 2) + 1].add(2 * m + 2 * prv[e] + 0);
                    RF[2 * m + 2 * prv[e] + 0].add(2 * (e / 2) + 1);
                }
                if (nxt[e] != -1) {
                    F[2 * m + 2 * e + 1].add(2 * m + 2 * nxt[e] + 1);
                    RF[2 * m + 2 * nxt[e] + 1].add(2 * m + 2 * e + 1);
                    F[2 * (e / 2) + 1].add(2 * m + 2 * nxt[e] + 1);
                    RF[2 * m + 2 * nxt[e] + 1].add(2 * (e / 2) + 1);
                }
            }
        }

        col = new int[6 * m];
        int ans = 0;
        int l = -1, r = inf;
        //int l = 999755901, r = l + 1;
        //int l = 999522589 - 1, r = 999522589 + 1;
        while (r - l > 1) {
            int q = (l + r) / 2;
            if (can(q)) {
                r = q;
            } else {
                l = q;
            }
        }
        if (r == inf) {
            writer.printf("No\n");
        } else {
            can(r);
            writer.printf("Yes\n");
            writer.printf("%d %d\n", r, enabled.size());
            for (int e : enabled)
                writer.printf("%d ", e + 1);
            writer.printf("\n");
        }
    }


    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

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

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }
    }

    static class OutputWriter {
        public PrintWriter writer;

        OutputWriter(OutputStream stream) {
            writer = new PrintWriter(stream);
        }

        public void printf(String format, Object... args) {
            writer.print(String.format(Locale.ENGLISH, format, args));
        }
    }
}

