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.*;

public class CFD {

    BufferedReader br;
    PrintWriter out;
    StringTokenizer st;
    boolean eof;
    final long MOD = 1000L * 1000L * 1000L + 7;
    int[] dx = {0, -1, 0, 1};
    int[] dy = {1, 0, -1, 0};

    int n;
    int m;
    boolean[][] graph;
    int[] vis;
    List<Integer> path = new ArrayList<>();
    void solve() throws IOException {
        n = nextInt();
        m = nextInt();
        graph = new boolean[n][n];

        for (int i = 0; i < m; i++) {
            int u = nextInt() - 1;
            int v = nextInt() - 1;
            graph[u][v] = true;
        }

        vis = new int[n];
        for (int i = 0; i < n; i++) {
            if (vis[i] == 0 && dfs(i, path) != -1) {
                break;
            }
        }

        if(path.isEmpty()) {
            out("YES");
            return;
        }

        path.add(path.get(0));
        Collections.reverse(path);

        for (int i = 0; i < path.size() - 1; i++) {
            int u = path.get(i);
            int v = path.get(i + 1);

            graph[u][v] = false;
            if (!hasCycle()) {
                out("YES");
                return;
            }

            graph[u][v] = true;
        }

        out("NO");
    }

    int dfs(int v, List<Integer> ans) {
        if (vis[v] == 2) return -1;
        if (vis[v] == 1) {
            ans.add(v);
            return v;
        }

        vis[v] = 1;
        for (int i = 0; i < n; i++) {
            if (graph[v][i]) {
                int vc = dfs(i, ans);
                if (vc == -2) {
                    return vc;
                }
                if (vc != -1) {
                    if (v == vc) {
                        return -2;
                    }
                    ans.add(v);
                    return vc;
                }

            }
        }
        vis[v] = 2;
        return -1;
    }





    boolean hasCycle() {
        int[] indegree = new int[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (graph[i][j]) {
                    indegree[j]++;
                }
            }
        }

        Deque<Integer> deck = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            if (indegree[i] == 0) {
                deck.add(i);
            }
        }
        while (!deck.isEmpty()) {
            int cur = deck.removeFirst();
            for (int i = 0; i < n; i++) {
                if (graph[cur][i]) {
                    indegree[i]--;
                    if (indegree[i] == 0) {
                        deck.add(i);
                    }
                }
            }
        }
        for (int i = 0; i < n; i++) {
            if (indegree[i] != 0) {
                return true;
            }
        }

        return false;
    }



    void shuffle(int[] a) {
        int n = a.length;
        for(int i = 0; i < n; i++) {
            int r = i + (int) (Math.random() * (n - i));
            int tmp = a[i];
            a[i] = a[r];
            a[r] = tmp;
        }
    }
    private void outln(Object o) {
        out.println(o);
    }
    private void out(Object o) {
        out.print(o);
    }
    public CFD() throws IOException {
        br = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        solve();
        out.close();
    }
    public static void main(String[] args) throws IOException {
        new CFD();
    }

    public long[] nextLongArr(int n) throws IOException{
        long[] res = new long[n];
        for(int i = 0; i < n; i++)
            res[i] = nextLong();
        return res;
    }
    public int[] nextIntArr(int n) throws IOException {
        int[] res = new int[n];
        for(int i = 0; i < n; i++)
            res[i] = nextInt();
        return res;
    }
    public String nextToken() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception e) {
                eof = true;
                return null;
            }
        }
        return st.nextToken();
    }
    public String nextString() {
        try {
            return br.readLine();
        } catch (IOException e) {
            eof = true;
            return null;
        }
    }
    public int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }
    public long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }
    public double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
}
