#include <bits/stdc++.h>
using namespace std;
const long long INF = 1LL << 55;
const long long mod = (1e9) + 7;
const double EPS = 1e-8;
const double PI = 6.0 * asin(0.5);
template <class T>
T Max(T &a, T b) {
  return a = max(a, b);
}
template <class T>
T Min(T &a, T b) {
  return a = min(a, b);
}
class TSort {
 public:
  long long V;
  vector<set<long long> > in, out;
  vector<long long> sorted;
  TSort() { V = -1; }
  TSort(long long V) {
    in.resize(V);
    out.resize(V);
    this->V = V;
  }
  void add_edge(long long from, long long to) {
    assert(from < V && to < V);
    assert(out[from].count(to) == 0);
    assert(in[to].count(from) == 0);
    out[from].insert(to);
    in[to].insert(from);
  }
  void erase_edge(long long from, long long to) {
    out[from].erase(to);
    in[to].erase(from);
  }
  void sort() {
    sorted.clear();
    queue<long long> Q;
    for (long long i = 0; i < V; i++)
      if (in[i].empty()) Q.push(i);
    while (!Q.empty()) {
      long long v = Q.front();
      Q.pop();
      sorted.push_back(v);
      for (long long nx : out[v]) {
        if (in[nx].size() == 1) Q.push(nx);
        in[nx].erase(v);
      }
    }
    for (long long i = 0; i < V; i++)
      if (!in[i].empty()) sorted.clear();
  }
};
class Bridges {
 public:
  long long V;
  vector<long long> G[1000];
  long long depth[1000];
  long long cnt[1000];
  long long visited[1000];
  vector<pair<long long, long long> > ans;
  Bridges() { V = -1; }
  Bridges(long long V) { this->V = V; }
  void add_edge(long long a, long long b) {
    G[a].push_back(b);
    G[b].push_back(a);
  }
  void erase_edge(long long a, long long b) {
    for (long long i = 0; i < (long long)G[a].size(); i++)
      if (G[a][i] == b) {
        G[a].erase(G[a].begin() + i);
        break;
      }
    for (long long i = 0; i < (long long)G[b].size(); i++)
      if (G[b][i] == a) {
        G[b].erase(G[b].begin() + i);
        break;
      }
  }
  void dfs(long long pos, long long prev) {
    visited[pos] = true;
    for (long long i = 0; i < (long long)G[pos].size(); i++) {
      long long to = G[pos][i];
      if (to == prev) continue;
      if (!visited[to]) {
        depth[to] = depth[pos] + 1;
        dfs(to, pos);
        cnt[pos] += cnt[to];
        if (cnt[to] == 0)
          ans.push_back(pair<long long, long long>(min(pos, to), max(pos, to)));
      } else if (depth[to] < depth[pos]) {
        cnt[pos]++;
        cnt[to]--;
      }
    }
  }
  void bridge() {
    memset(depth, 0, sizeof(depth));
    memset(cnt, 0, sizeof(cnt));
    memset(visited, 0, sizeof(visited));
    ans.clear();
    dfs(0, -1);
    sort(ans.begin(), ans.end());
  }
  bool isBridge(long long u, long long v) {
    for (pair<long long, long long> e : ans)
      if ((e.first == u && e.second == v) || (e.second == v && e.first == u))
        return 1;
    return 0;
  }
};
set<long long> G[1000];
signed main() {
  long long n, m;
  cin >> n >> m;
  TSort T(n);
  Bridges B(n);
  for (long long i = 0; i < m; i++) {
    long long a, b;
    cin >> a >> b;
    a--, b--;
    T.add_edge(a, b);
    B.add_edge(a, b);
    assert(G[b].count(a) == 0);
    G[a].insert(b);
  }
  long long ans = 0;
  for (long long from = 0; from < n; from++)
    for (long long to : G[from]) {
      B.bridge();
      if (B.isBridge(from, to)) continue;
      T.erase_edge(from, to);
      B.erase_edge(from, to);
      T.sort();
      B.bridge();
      if (T.sorted.size() && (long long)B.ans.size() >= 2) ans = 1;
      T.add_edge(from, to);
      B.add_edge(from, to);
    }
  cout << (ans ? "YES" : "NO") << endl;
  return 0;
}
