#include <bits/stdc++.h>
using namespace std;
void add_edge(int u, int v);
void dfs(int u, const int &index);
bool binary_enum(int c);
const int MAX = 1e6 + 5, MAXS = 25;
vector<int> graph[MAX];
vector<int> source, sink;
set<int> reachable[MAXS];
int degree[2][MAX];
bool visited[MAX];
int main() {
  int n, m;
  while (scanf("%d %d", &n, &m) != EOF) {
    for (int i = 0; i < MAX; i++) {
      graph[i].clear();
    }
    source.clear();
    sink.clear();
    for (int i = 0; i < MAXS; i++) {
      reachable[i].clear();
    }
    memset(degree, 0, sizeof(degree));
    int v, u;
    while (m--) {
      scanf("%d %d", &v, &u);
      add_edge(v, u);
    }
    for (int u = 1; u <= n; u++) {
      if (degree[0][u] == 0) source.push_back(u);
      if (degree[1][u] == 0) sink.push_back(u);
    }
    for (int i = 0; i < source.size(); i++) {
      memset(visited, false, sizeof(visited));
      dfs(source[i], i);
    }
    bool res = binary_enum(source.size());
    printf(res ? "YES\n" : "NO\n");
  }
  return 0;
}
inline void add_edge(int u, int v) {
  graph[u].push_back(v);
  degree[0][v]++;
  degree[1][u]++;
}
void dfs(int u, const int &index) {
  if (degree[1][u] == 0) {
    reachable[index].insert(u);
  }
  visited[u] = true;
  for (int i = 0; i < graph[u].size(); i++) {
    int v = graph[u][i];
    if (!visited[v]) {
      dfs(v, index);
    }
  }
}
bool binary_enum(int c) {
  set<int> s;
  for (int status = 1; status < (1 << c) - 1; status++) {
    s.clear();
    int cnt = 0;
    for (int i = 0; i < c; i++) {
      if ((status >> i) & 1) {
        s.insert(reachable[i].begin(), reachable[i].end());
        cnt++;
      }
    }
    if (cnt >= s.size()) {
      return false;
    }
  }
  return true;
}
