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.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;


public class d {
	static boolean dfs(int start, boolean[] onStack, int bu, int bv) {
		ArrayDeque<Integer> s = new ArrayDeque<Integer>();
		onStack[start] = true;
		visited[start] = true;
		s.push(start);
		s.push(0);

		while (!s.isEmpty()) {
			int child = s.pop();
			int node = s.pop();
			if (child == adj[node].size())
				onStack[node] = false;
			else {
				int next = adj[node].get(child);
				s.push(node);
				s.push(++child);
				if(node == bu && next == bv)
					continue;
				if (onStack[next])
					return true;
				if (!visited[next]) {
					visited[next] = true;
					onStack[next] = true;
					s.push(next);
					s.push(0);
				}
			}
		}
		return false;
	}
	
	static boolean getCycle(int start, boolean[] onStack, int bu, int bv, ArrayList<Integer> cyc) {
		ArrayDeque<Integer> s = new ArrayDeque<Integer>();
		onStack[start] = true;
		visited[start] = true;
		s.push(start);
		s.push(0);
//		System.out.println("ST " + start);
		while (!s.isEmpty()) {
			int child = s.pop();
			int node = s.pop();
//			System.out.println(node  + " " + s);
			if (child == adj[node].size())
				onStack[node] = false;
			else {
				int next = adj[node].get(child);
//				System.out.println(adj[node]);
//				System.out.println(node + " " + next);
				s.push(node);
				s.push(++child);
				if(node == bu && next == bv)
					continue;
				if (onStack[next]) {
//					System.out.println(s);
					while(!s.isEmpty()) {
						s.poll();
						cyc.add(s.poll());
					}
					Collections.reverse(cyc);
					return true;
				}
				if (!visited[next]) {
					visited[next] = true;
					onStack[next] = true;
					s.push(next);
					s.push(0);
				}
			}
		}
		return false;
	}
	
	static boolean visited[];
	static ArrayList<Integer> adj[];
	public static List<Integer> topSort() {
		Stack<Integer> stack = new Stack<Integer>();
		for (int i = 0; i < adj.length; i++)
			if (!visited[i])
				topSortDfs(i, stack);
		
		List<Integer> ans = new ArrayList<Integer>(stack);
		Collections.reverse(ans);
		return ans;
	}

	public static void topSortDfs(int n, Stack<Integer> stack) {
		visited[n] = true;
		for (int i = 0; i < adj[n].size(); i++)
			if (!visited[adj[n].get(i)])
				topSortDfs(adj[n].get(i), stack);
		
		stack.push(n);
	}
	
	public static void main(String args[]) throws IOException {
		FastScanner in = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);
		// BEGIN HERE
		int n = in.nextInt();
		int m = in.nextInt();
		adj = new ArrayList[n];
		for (int i = 0; i < n; i++)
			adj[i] = new ArrayList<>();
		for (int i = 0; i < m; i++) {
			adj[in.nextInt()-1].add(in.nextInt()-1);
		}
		visited = new boolean[n];
		boolean onStack[] = new boolean[n];
		List<Integer> order = topSort();
		Collections.reverse(order);
//		System.out.println(order);
		visited = new boolean[n];
		ArrayList<Integer> cycle = new ArrayList<>();
		for(int i = 0; i < n; i++) {
			if(!visited[order.get(i)]) {
//				System.out.println("ER");
				if(getCycle(order.get(i), onStack, -1, -1, cycle)) {
//					System.out.println("HERE");
					break;
				}
			}
		}
//		System.out.println(cycle);
		if(cycle.size() == 0) {
			System.out.println("YES");
			return;
		}
		for(int i = 0; i < cycle.size(); i++) {
			visited = new boolean[n];
			onStack = new boolean[n];
			boolean pos = true;
			for(int j = 0; j < n; j++) {
				int v = order.get(j);
				if(!visited[v])
					if(dfs(v, onStack, cycle.get(i), cycle.get(i +1 == cycle.size() ? 0 : i+1))) {
						pos = false;
						break;
					}
			}
			if(pos) {
				System.out.println("YES");
				return;
			}
		}
		System.out.println("NO");
		out.close();
	}

	static class FastScanner {
		BufferedReader br;
		StringTokenizer st;

		public FastScanner(InputStream i) {
			br = new BufferedReader(new InputStreamReader(i));
			st = null;
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public String nextLine() throws IOException {
			if (st == null) {
				st = new StringTokenizer(br.readLine());
			}
			String line = st.nextToken("\n");
			st = null;
			return line;
		}

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

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

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

	public static class combinatorics {
		static long modInv(long a, long b) {
			return 1 < a ? b - modInv(b % a, a) * b / a : 1;
		}

		static long factorial[], mod;

		combinatorics(int n, long MOD) {
			mod = MOD;
			factorial = new long[n + 1];
			factorial[0] = 1;
			for (int i = 1; i <= n; i++) {
				factorial[i] = i * factorial[i - 1];
				factorial[i] %= mod;
			}
		}

		static long nCr(int n, int r) {
			if (r > n)
				return 0;
			return (factorial[n] * modInv((factorial[n - r] * factorial[r]) % mod, mod)) % mod;
		}

		static long gcd(long a, long b) {
			return b == 0 ? a : gcd(b, a % b);
		}

		static long lcm(long a, long b) {
			return a * (b / gcd(a, b));
		}
	}

	public static class DisjointSet {
		int p[], r[], s[];
		int numDisjoint;

		DisjointSet(int N) {
			numDisjoint = N;
			r = new int[N];
			s = new int[N];
			p = new int[N];
			for (int i = 0; i < N; i++)
				p[i] = i;
		}

		int findSet(int i) {
			return (p[i] == i) ? i : (p[i] = findSet(p[i]));
		}

		boolean isSameSet(int i, int j) {
			return findSet(i) == findSet(j);
		}

		void unionSet(int i, int j) {
			if (!isSameSet(i, j)) // if from different set
			{
				numDisjoint--;
				int x = findSet(i), y = findSet(j);
				if (r[x] > r[y]) {
					p[y] = x; // rank keeps the tree short
					s[x] += s[y];
				} else {
					p[x] = y;
					if (r[x] == r[y])
						r[y]++;
					s[y] += s[x];
				}
			}
		}

		int sizeOfSet(int i) {
			return s[findSet(i)];
		}
	};

}