#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline bool RD(T& v) {
  char c;
  bool n;
  while (c = getchar(), c != '-' && (c < '0' || c > '9'))
    if (c == EOF) return false;
  if (c == '-') {
    n = true;
    v = 0;
  } else {
    n = false;
    v = c - '0';
  }
  while (c = getchar(), c >= '0' && c <= '9') v = (v << 3) + (v << 1) + c - '0';
  if (n) v *= -1;
  return true;
}
template <typename A, typename... Args>
inline bool RD(A& a, Args&... rest) {
  return RD(a) && RD(rest...);
}
inline int RD() {
  int v;
  RD(v);
  return v;
}
inline char getchar_buffered() {
  static char _BUF_[1 << 15], *_HEAD_ = _BUF_, *_TAIL_ = _BUF_;
  return _HEAD_ == _TAIL_ &&
                 (_TAIL_ = (_HEAD_ = _BUF_) + fread(_BUF_, 1, 1 << 15, stdin),
                  _HEAD_ == _TAIL_)
             ? EOF
             : *_HEAD_++;
}
template <typename T>
inline bool RDB(T& v) {
  char c;
  bool n;
  while (c = getchar_buffered(), c != '-' && (c < '0' || c > '9'))
    if (c == EOF) return false;
  if (c == '-') {
    n = true;
    v = 0;
  } else {
    n = false;
    v = c - '0';
  }
  while (c = getchar_buffered() - '0', c >= 0 && c <= 9)
    v = (v << 3) + (v << 1) + c;
  if (n) v *= -1;
  return true;
}
template <typename A, typename... Args>
inline bool RDB(A& a, Args&... rest) {
  return RDB(a) && RDB(rest...);
}
inline int RDB() {
  int v;
  RDB(v);
  return v;
}
template <typename T>
inline void _WR(T a) {
  if (a < 0) {
    putchar('-');
    a *= -1;
  }
  T t = a / 10;
  if (t) _WR(t);
  putchar(a - (t << 1) - (t << 3) + '0');
}
template <typename T>
inline void WR_(const T& a) {
  _WR(a);
  putchar(' ');
}
template <typename T>
inline void WR(const T& a) {
  _WR(a);
  putchar('\n');
}
template <typename A, typename... Args>
inline void _WR(const A& a, const Args&... rest) {
  WR_(a);
  _WR(rest...);
}
template <typename A, typename... Args>
inline void WR_(const A& a, const Args&... rest) {
  WR_(a);
  WR_(rest...);
}
template <typename A, typename... Args>
inline void WR(const A& a, const Args&... rest) {
  WR_(a);
  WR(rest...);
}
const int inf = 0x3f3f3f3f;
const int maxn = 1e6 + 10;
int n, m;
vector<int> eout[maxn], ein[maxn], es[maxn];
vector<int> sources, sinks;
void no() {
  puts("NO");
  exit(0);
}
void yes() {
  puts("YES");
  exit(0);
}
bool is_source(int i) { return ein[i].size() == 0; }
bool is_sink(int i) { return eout[i].size() == 0; }
void process_source(int s) {
  vector<bool> vis(n + 1, false);
  vis[s] = true;
  vector<int> to_sinks;
  vector<int> t = eout[s];
  while (t.size()) {
    int u = t.back();
    t.pop_back();
    if (vis[u]) continue;
    vis[u] = true;
    if (is_sink(u)) {
      to_sinks.push_back(u);
      continue;
    }
    t.insert(t.end(), eout[u].begin(), eout[u].end());
  }
  es[s].swap(to_sinks);
}
int cntbit(int x) {
  int ret = 0;
  while (x) {
    int lb = x & -x;
    x -= lb;
    ++ret;
  }
  return ret;
}
int main() {
  RDB(n, m);
  for (int i = 0; i < (int)(m); ++i) {
    int u, v;
    RDB(u, v);
    eout[u].push_back(v);
    ein[v].push_back(u);
  }
  for (int i = 1; i < (int)(n + 1); ++i) {
    if (is_source(i) && is_sink(i)) no();
    if (is_source(i)) sources.push_back(i);
    if (is_sink(i)) sinks.push_back(i);
  }
  for (int s : sources) process_source(s);
  map<int, int> sink_to_idx;
  for (int i = 0; i < (int)(sinks.size()); ++i) sink_to_idx[sinks[i]] = i;
  vector<int> e_bm(sources.size(), 0);
  for (int i = 0; i < (int)(sources.size()); ++i) {
    for (int t : es[sources[i]]) {
      e_bm[i] |= 1 << sink_to_idx[t];
    }
  }
  for (int i = 1; i < (int)((1 << sources.size()) - 1); ++i) {
    int k = 0;
    for (int j = 0; j < (int)(sources.size()); ++j)
      if (i & 1 << j) k |= e_bm[j];
    if (cntbit(k) <= cntbit(i)) no();
  }
  yes();
  return 0;
}
