#include <bits/stdc++.h>
using namespace std;
const int NMAX = 1000;
bool viz[NMAX + 2];
vector<int> G[NMAX + 2], GP[NMAX + 2], ord, ind_ctc;
int N, M;
vector<vector<int>> ctc;
void Dfs_Plus(int nod) {
  viz[nod] = 1;
  for (int i = 0; i < (int)G[nod].size(); ++i) {
    int x = G[nod][i];
    if (!viz[x]) {
      Dfs_Plus(x);
    }
  }
  ord.push_back(nod);
}
void Dfs_Minus(int nod) {
  viz[nod] = 1;
  ind_ctc.push_back(nod);
  for (int i = 0; i < (int)GP[nod].size(); ++i) {
    int x = GP[nod][i];
    if (!viz[x]) {
      Dfs_Minus(x);
    }
  }
}
bool blocat[NMAX + 2][NMAX + 2];
int tata[NMAX + 2], fain[NMAX + 2], vv2[NMAX + 2], gataciclu = 0,
                                                   oncycle[NMAX + 2];
stack<int> stk, nst;
vector<pair<int, int>> badlist;
void DFS1(int nod) {
  if (gataciclu) return;
  vv2[nod] = 1;
  stk.push(nod);
  for (auto x : G[nod]) {
    assert(1 <= x && x <= NMAX);
    if (vv2[x]) {
      if (gataciclu) return;
      gataciclu = 1;
      oncycle[nod] = oncycle[x] = 1;
      badlist.push_back({nod, x});
      while (stk.size() > 1) {
        int unu = stk.top();
        stk.pop();
        assert(!stk.empty());
        int doi = stk.top();
        if (oncycle[unu] >= 2) break;
        badlist.push_back({doi, unu});
        oncycle[doi]++;
        oncycle[unu]++;
      }
    } else if (fain[x] && !vv2[x]) {
      if (gataciclu) return;
      DFS1(x);
    }
  }
  stk.pop();
}
void mark1(int nod) {
  memset(tata, 0, sizeof(tata));
  DFS1(nod);
}
bool find_new = 0, onstack[NMAX + 2];
int timestamp = 0;
void DF(int nod) {
  vv2[nod] = timestamp;
  nst.push(nod);
  onstack[nod] = 1;
  if (find_new) return;
  for (auto x : G[nod]) {
    assert(1 <= x && x <= NMAX);
    if (blocat[nod][x]) continue;
    if (!fain[x]) continue;
    if (vv2[x] == timestamp && onstack[x]) {
      find_new = 1;
    }
    if (fain[x] && !vv2[x]) {
      DF(x);
    }
  }
  onstack[nst.top()] = 0;
  nst.pop();
}
int main() {
  cin >> N >> M;
  for (int i = 1; i <= M; ++i) {
    int x, y;
    cin >> x >> y;
    G[x].push_back(y);
    GP[y].push_back(x);
  }
  for (int i = 1; i <= N; ++i) {
    if (!viz[i]) Dfs_Plus(i);
  }
  memset(viz, 0, sizeof(viz));
  for (int i = (int)ord.size() - 1; i >= 0; --i) {
    if (!viz[ord[i]]) {
      ind_ctc.clear();
      Dfs_Minus(ord[i]);
      sort(ind_ctc.begin(), ind_ctc.end());
      ctc.push_back(ind_ctc);
    }
  }
  vector<int> nodes;
  int big_ctc = 0;
  for (auto lt : ctc) {
    if (lt.size() > 1) {
      ++big_ctc;
      for (auto x : lt) {
        nodes.push_back(x);
        fain[x] = 1;
      }
    }
  }
  if (big_ctc > 1) {
    cout << "NO\n";
    return 0;
  }
  if (big_ctc < 1) {
    cout << "YES\n";
    return 0;
  }
  assert(nodes.size() > 1);
  mark1(nodes.back());
  find_new = 0;
  for (auto pp : badlist) {
    blocat[pp.first][pp.second] = 1;
    memset(vv2, 0, sizeof(vv2));
    find_new = 0;
    for (auto x : nodes) {
      if (!vv2[x]) {
        ++timestamp;
        DF(x);
      }
    }
    if (!find_new) {
      cout << "YES\n";
      return 0;
    }
    blocat[pp.first][pp.second] = 0;
  }
  cout << "NO\n";
  return 0;
}
