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

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

  static class TaskD {
    Graph g;
    int n;
    int m;
    boolean[] inTree;
    int[] path;
    boolean[] used;

    List<Integer> extractCycle(int lastEdge, int lastV, int pathLen) {
      List<Integer> cycleEdges = new ArrayList<>();
      cycleEdges.add(lastEdge);
      for (int cycleEdgeIx = pathLen - 1; cycleEdgeIx >= 0 && g.destination(path[cycleEdgeIx]) != lastV; --cycleEdgeIx) {
        cycleEdges.add(path[cycleEdgeIx]);
      }
      return cycleEdges;
    }

    List<Integer> findCycleDfs(int v, int pathLen) {
      used[v] = true;
      inTree[v] = true;
      for (int e = g.firstOutbound(v); e != -1; e = g.nextOutbound(e)) {
        int kid = g.destination(e);
        if (inTree[kid]) {
          return extractCycle(e, kid, pathLen);
        } else if (!used[kid]) {
          path[pathLen] = e;
          List<Integer> cycleEdges = findCycleDfs(kid, pathLen + 1);
          if (cycleEdges != null) {
            return cycleEdges;
          }
        }
      }
      inTree[v] = false;
      return null;
    }

    List<Integer> getRandomSimpleCycle() {
      Arrays.fill(inTree, false);
      Arrays.fill(used, false);
      List<Integer> cycleEdges = null;
      for (int i = 0; i < n && cycleEdges == null; ++i) {
        if (!used[i]) {
          cycleEdges = findCycleDfs(i, 0);
        }
      }
      return cycleEdges;
    }

    public void solve(int testNumber, InputStreamReader in, PrintWriter out) {
      SvScanner sc = new SvScanner(in);
      n = sc.nextInt();
      m = sc.nextInt();
      g = new Graph(n, m);

      for (int i = 0; i < m; ++i) {
        int u = sc.nextInt() - 1;
        int v = sc.nextInt() - 1;
        g.addSimpleEdge(u, v);
      }

      inTree = new boolean[n];
      used = new boolean[n];
      path = new int[n];

      List<Integer> cycleEdges = getRandomSimpleCycle();
//    out.println(cycleEdges);
      if (cycleEdges == null) {
        out.println("YES");
      } else {
        for (int edgeToRemove : cycleEdges) {
          g.removeEdge(edgeToRemove);
          if (getRandomSimpleCycle() == null) {
            out.println("YES");
            return;
          }
          g.restoreEdge(edgeToRemove);
        }
        out.println("NO");
      }
    }

  }

  static class Graph {
    public static final int REMOVED_BIT = 0;
    protected int vertexCount;
    protected int edgeCount;
    private int[] firstOutbound;
    private int[] firstInbound;
    private Edge[] edges;
    private int[] nextInbound;
    private int[] nextOutbound;
    private int[] from;
    private int[] to;
    private long[] weight;
    public long[] capacity;
    private int[] reverseEdge;
    private int[] flags;

    public Graph(int vertexCount) {
      this(vertexCount, vertexCount);
    }

    public Graph(int vertexCount, int edgeCapacity) {
      this.vertexCount = vertexCount;
      firstOutbound = new int[vertexCount];
      Arrays.fill(firstOutbound, -1);

      from = new int[edgeCapacity];
      to = new int[edgeCapacity];
      nextOutbound = new int[edgeCapacity];
      flags = new int[edgeCapacity];
    }

    public int addEdge(int fromID, int toID, long weight, long capacity, int reverseEdge) {
      ensureEdgeCapacity(edgeCount + 1);
      if (firstOutbound[fromID] != -1) {
        nextOutbound[edgeCount] = firstOutbound[fromID];
      } else {
        nextOutbound[edgeCount] = -1;
      }
      firstOutbound[fromID] = edgeCount;
      if (firstInbound != null) {
        if (firstInbound[toID] != -1) {
          nextInbound[edgeCount] = firstInbound[toID];
        } else {
          nextInbound[edgeCount] = -1;
        }
        firstInbound[toID] = edgeCount;
      }
      this.from[edgeCount] = fromID;
      this.to[edgeCount] = toID;
      if (capacity != 0) {
        if (this.capacity == null) {
          this.capacity = new long[from.length];
        }
        this.capacity[edgeCount] = capacity;
      }
      if (weight != 0) {
        if (this.weight == null) {
          this.weight = new long[from.length];
        }
        this.weight[edgeCount] = weight;
      }
      if (reverseEdge != -1) {
        if (this.reverseEdge == null) {
          this.reverseEdge = new int[from.length];
          Arrays.fill(this.reverseEdge, 0, edgeCount, -1);
        }
        this.reverseEdge[edgeCount] = reverseEdge;
      }
      if (edges != null) {
        edges[edgeCount] = createEdge(edgeCount);
      }
      return edgeCount++;
    }

    protected final GraphEdge createEdge(int id) {
      return new GraphEdge(id);
    }

    public final int addFlowWeightedEdge(int from, int to, long weight, long capacity) {
      if (capacity == 0) {
        return addEdge(from, to, weight, 0, -1);
      } else {
        int lastEdgeCount = edgeCount;
        addEdge(to, from, -weight, 0, lastEdgeCount + entriesPerEdge());
        return addEdge(from, to, weight, capacity, lastEdgeCount);
      }
    }

    protected int entriesPerEdge() {
      return 1;
    }

    public final int addWeightedEdge(int from, int to, long weight) {
      return addFlowWeightedEdge(from, to, weight, 0);
    }

    public final int addSimpleEdge(int from, int to) {
      return addWeightedEdge(from, to, 0);
    }

    public final int firstOutbound(int vertex) {
      int id = firstOutbound[vertex];
      while (id != -1 && isRemoved(id)) {
        id = nextOutbound[id];
      }
      return id;
    }

    public final int nextOutbound(int id) {
      id = nextOutbound[id];
      while (id != -1 && isRemoved(id)) {
        id = nextOutbound[id];
      }
      return id;
    }

    public final int destination(int id) {
      return to[id];
    }

    public final boolean flag(int id, int bit) {
      return (flags[id] >> bit & 1) != 0;
    }

    public final void setFlag(int id, int bit) {
      flags[id] |= 1 << bit;
    }

    public final void removeFlag(int id, int bit) {
      flags[id] &= -1 - (1 << bit);
    }

    public final void removeEdge(int id) {
      setFlag(id, REMOVED_BIT);
    }

    public final void restoreEdge(int id) {
      removeFlag(id, REMOVED_BIT);
    }

    public final boolean isRemoved(int id) {
      return flag(id, REMOVED_BIT);
    }

    protected void ensureEdgeCapacity(int size) {
      if (from.length < size) {
        int newSize = Math.max(size, 2 * from.length);
        if (edges != null) {
          edges = resize(edges, newSize);
        }
        from = resize(from, newSize);
        to = resize(to, newSize);
        nextOutbound = resize(nextOutbound, newSize);
        if (nextInbound != null) {
          nextInbound = resize(nextInbound, newSize);
        }
        if (weight != null) {
          weight = resize(weight, newSize);
        }
        if (capacity != null) {
          capacity = resize(capacity, newSize);
        }
        if (reverseEdge != null) {
          reverseEdge = resize(reverseEdge, newSize);
        }
        flags = resize(flags, newSize);
      }
    }

    protected final int[] resize(int[] array, int size) {
      int[] newArray = new int[size];
      System.arraycopy(array, 0, newArray, 0, array.length);
      return newArray;
    }

    private long[] resize(long[] array, int size) {
      long[] newArray = new long[size];
      System.arraycopy(array, 0, newArray, 0, array.length);
      return newArray;
    }

    private Edge[] resize(Edge[] array, int size) {
      Edge[] newArray = new Edge[size];
      System.arraycopy(array, 0, newArray, 0, array.length);
      return newArray;
    }

    protected class GraphEdge implements Edge {
      protected int id;

      protected GraphEdge(int id) {
        this.id = id;
      }

    }

  }

  static class SvScanner {
    private BufferedReader reader;
    private StringTokenizer tokenizer = new StringTokenizer("");

    public SvScanner(InputStreamReader in) {
      reader = new BufferedReader(in);
    }

    public String next() {
      try {
        while (!tokenizer.hasMoreTokens()) {
          String nextLine = reader.readLine();
          if (nextLine == null) {
            throw new IllegalStateException("next line is null");
          }
          tokenizer = new StringTokenizer(nextLine);
        }
        return tokenizer.nextToken();
      } catch (IOException e) {
        throw new IllegalStateException(e);
      }
    }

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

  }

  static interface Edge {
  }
}

