You are given a [directed graph](https://en.wikipedia.org/wiki/Directed_graph) consisting of n vertices and m edges (each edge is directed, so it can be traversed in only one direction). You are allowed to remove at most one edge from it.

Can you make this graph [acyclic](https://en.wikipedia.org/wiki/Directed_acyclic_graph) by removing at most one edge from it? A directed graph is called acyclic iff it doesn't contain any cycle (a non-empty path that starts and ends in the same vertex).

Input

The first line contains two integers n and m (2 ≤ n ≤ 500, 1 ≤ m ≤ min(n(n - 1), 100000)) — the number of vertices and the number of edges, respectively.

Then m lines follow. Each line contains two integers u and v denoting a directed edge going from vertex u to vertex v (1 ≤ u, v ≤ n, u ≠ v). Each ordered pair (u, v) is listed at most once (there is at most one directed edge from u to v).

Output

If it is possible to make this graph acyclic by removing at most one edge, print YES. Otherwise, print NO.

Examples

Input

3 4
1 2
2 3
3 2
3 1


Output

YES


Input

5 6
1 2
2 3
3 2
3 1
2 1
4 5


Output

NO

Note

In the first example you can remove edge <image>, and the graph becomes acyclic.

In the second example you have to remove at least two edges (for example, <image> and <image>) in order to make the graph acyclic.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
	try (BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(System.out);) {
	    StringTokenizer st;

	    st = new StringTokenizer(in.readLine());
	    int n = Integer.parseInt(st.nextToken());
	    int m = Integer.parseInt(st.nextToken());

	    List<List<Integer>> graph = new ArrayList<>();
	    for (int i = 0; i < n; i++) {
		graph.add(new ArrayList<>());
	    }
	    List<List<Integer>> reverse = new ArrayList<>();
	    for (int i = 0; i < n; i++) {
		reverse.add(new ArrayList<>());
	    }
	    int[] src = new int[m];
	    int[] trg = new int[m];
	    for (int i = 0; i < m; i++) {
		st = new StringTokenizer(in.readLine());
		int u = Integer.parseInt(st.nextToken()) - 1;
		int v = Integer.parseInt(st.nextToken()) - 1;
		graph.get(u).add(v);
		reverse.get(v).add(u);
		src[i] = u;
		trg[i] = v;
	    }

	    boolean[] visited = new boolean[n];
	    List<Integer> reverseTopo = new ArrayList<>();
	    for (int i = 0; i < n; i++) {
		if (!visited[i]) {
		    dfs(reverse, visited, reverseTopo, i);
		}
	    }

	    int[] scc = new int[n];
	    int count = 0;
	    for (int i = n - 1; i >= 0; i--) {
		int v = reverseTopo.get(i);
		if (scc[v] == 0) {
		    count++;
		    dfs(graph, scc, v, count);
		}
	    }

	    int[] counts = new int[count + 1];
	    for (int i = 0; i < n; i++) {
		counts[scc[i]]++;
	    }

	    int component = -1;
	    boolean possible = true;
	    for (int i = 1; i <= count && possible; i++) {
		if (counts[i] > 1) {
		    if (component == -1) {
			component = i;
		    } else {
			possible = false;
		    }
		}
	    }

	    if (!possible) {
		out.println("NO");
	    } else if (component == -1) {
		out.println("YES");
	    } else {
		int index = 0;
		Map<Integer, Integer> mapping = new HashMap<>();
		for (int i = 0; i < n; i++) {
		    if (scc[i] == component) {
			mapping.put(i, index);
			index++;
		    }
		}

		int[] inDeg = new int[index];

		List<List<Integer>> newGraph = new ArrayList<>();
		for (int i = 0; i < index; i++) {
		    newGraph.add(new ArrayList<>());
		}
		for (int i = 0; i < m; i++) {
		    if (scc[src[i]] == component && scc[trg[i]] == component) {
			int u = mapping.get(src[i]);
			int v = mapping.get(trg[i]);
			inDeg[v]++;
			newGraph.get(u).add(v);
		    }
		}

		possible = false;
		for (int i = 0; i < index && !possible; i++) {
		    if (newGraph.get(i).size() == 1) {
			int v = newGraph.get(i).get(0);
			if (inDeg[v] == 1) {
			    newGraph.get(i).remove(0);

			    if (!detectCycle(newGraph)) {
				possible = true;
			    }

			    newGraph.get(i).add(v);
			}
		    }
		}

		if (possible) {
		    out.println("YES");
		} else {
		    out.println("NO");
		}
	    }
	}
    }

    private static boolean detectCycle(List<List<Integer>> graph) {
	int n = graph.size();
	boolean[] seen = new boolean[n];
	boolean[] finished = new boolean[n];
	for (int i = 0; i < n; i++) {
	    if (!seen[i]) {
		if (dfs(graph, seen, finished, i)) {
		    return true;
		}
	    }
	}
	return false;
    }

    private static boolean dfs(List<List<Integer>> graph, boolean[] seen, boolean[] finished, int u) {
	seen[u] = true;
	for (Integer v : graph.get(u)) {
	    if (!finished[v]) {
		if (seen[v]) {
		    return true;
		}
		if (dfs(graph, seen, finished, v)) {
		    return true;
		}
	    }
	}
	finished[u] = true;
	return false;
    }

    private static void dfs(List<List<Integer>> graph, int[] scc, int u, int count) {
	if (scc[u] != 0) {
	    return;
	}

	scc[u] = count;
	for (Integer v : graph.get(u)) {
	    dfs(graph, scc, v, count);
	}
    }

    private static void dfs(List<List<Integer>> graph, boolean[] visited, List<Integer> reverseTopo, int u) {
	if (visited[u]) {
	    return;
	}

	visited[u] = true;
	for (Integer v : graph.get(u)) {
	    dfs(graph, visited, reverseTopo, v);
	}
	reverseTopo.add(u);
    }
}
