#include <bits/stdc++.h>
using namespace std;
const long long inf = 1e9;
const long long mod = 1e9 + 7;
typedef pair<long long, long long> Edge;
class BICC {
 private:
  const long long n;
  vector<vector<long long>> G;
  vector<long long> depth;
  vector<long long> par;
  map<Edge, long long> imosEdge;
  map<Edge, long long> EdgeType;
  enum { UNUSED, USED_DFS, BRIDGE };
  vector<Edge> bridges;

 public:
  vector<long long> cmp;
  long long num_cc;
  vector<long long> size_of_vertex;
  vector<vector<long long>> G_cc;

 public:
  BICC(long long _n)
      : n(_n), G(_n), depth(_n, -1), par(_n, -1), cmp(_n, -1), num_cc(0) {}
  Edge getEdge(long long a, long long b) {
    if (a > b) swap(a, b);
    return Edge(a, b);
  }
  void updateEdgeType(long long a, long long b, long long type) {
    if (a < 0 || b < 0) return;
    EdgeType[getEdge(a, b)] = type;
  }
  void addEdge(long long a, long long b) {
    G[a].emplace_back(b);
    G[b].emplace_back(a);
    updateEdgeType(a, b, UNUSED);
  }
  void dfsTreeConstruct(long long v, long long pre) {
    if (depth[v] != -1) return;
    depth[v] = (pre == -1 ? 0 : depth[pre] + 1);
    par[v] = pre;
    updateEdgeType(pre, v, USED_DFS);
    for (auto&& nxt : G[v]) {
      if (nxt != pre) dfsTreeConstruct(nxt, v);
    }
  }
  void updateImos(long long a, long long b) {
    if (depth[a] < depth[b]) swap(a, b);
    if (par[a] != -1) {
      imosEdge[getEdge(a, par[a])]++;
    }
    if (par[b] != -1) {
      imosEdge[getEdge(b, par[b])]--;
    }
  }
  long long imosFinal(long long v, long long pre) {
    long long t = 0;
    for (auto&& nxt : G[v]) {
      if (nxt != pre && EdgeType[getEdge(nxt, v)] == USED_DFS) {
        t += imosFinal(nxt, v);
      }
    }
    if (pre != -1) imosEdge[getEdge(v, pre)] += t;
    return pre == -1 ? 0 : imosEdge[getEdge(v, pre)];
  }
  long long extractCC(long long v, long long color) {
    if (cmp[v] != -1) return 0;
    cmp[v] = color;
    long long t = 1;
    for (auto&& nxt : G[v]) {
      if (EdgeType[getEdge(v, nxt)] != BRIDGE) {
        t += extractCC(nxt, color);
      }
    }
    return t;
  }
  void bicc() {
    dfsTreeConstruct(0, -1);
    for (auto&& p : EdgeType) {
      Edge e;
      long long type;
      tie(e, type) = p;
      if (type == UNUSED) {
        updateImos(e.first, e.second);
      }
    }
    imosFinal(0, -1);
    for (auto&& p : EdgeType) {
      Edge e;
      long long type;
      tie(e, type) = p;
      if (type == USED_DFS) {
        if (imosEdge[e] == 0) {
          EdgeType[e] = BRIDGE;
          bridges.emplace_back(e);
        }
      }
    }
    for (long long i = 0; i < (n); i++) {
      long long size_cc = extractCC(i, num_cc);
      if (size_cc > 0) {
        size_of_vertex.emplace_back(size_cc);
        num_cc++;
      }
    }
    vector<set<long long>> G_cc_st(num_cc);
    for (auto&& p : EdgeType) {
      Edge e;
      long long type;
      tie(e, type) = p;
      if (type == BRIDGE) {
        G_cc_st[cmp[e.first]].insert(cmp[e.second]);
        G_cc_st[cmp[e.second]].insert(cmp[e.first]);
      }
    }
    for (long long i = 0; i < (num_cc); i++) {
      G_cc.emplace_back(
          vector<long long>((G_cc_st[i]).begin(), (G_cc_st[i]).end()));
    }
  }
  vector<Edge> getBridges() { return bridges; }
};
bool dfs(long long now, long long start, const vector<vector<long long>>& G,
         vector<bool>& visited) {
  visited[now] = true;
  for (auto nxt : G[now]) {
    if (nxt == start) return false;
    if (!visited[nxt] && !dfs(nxt, start, G, visited)) return false;
  }
  return true;
}
bool isDAG(const vector<vector<long long>>& G) {
  long long n = G.size();
  for (long long i = 0; i < (n); i++) {
    vector<bool> visited(n);
    if (!dfs(i, i, G, visited)) return false;
  }
  return true;
}
signed main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  long long N, M;
  cin >> N >> M;
  vector<pair<long long, long long>> edges;
  for (long long i = 0; i < (M); i++) {
    long long a, b;
    cin >> a >> b;
    a--, b--;
    edges.emplace_back(a, b);
  }
  for (long long i = 0; i < (M); i++) {
    BICC bicc(N);
    vector<vector<long long>> G_dir(N);
    for (long long j = 0; j < (M); j++) {
      if (j == i) continue;
      bicc.addEdge(edges[j].first, edges[j].second);
      G_dir[edges[j].first].emplace_back(edges[j].second);
    }
    bicc.bicc();
    if (bicc.num_cc >= 3 && isDAG(G_dir)) {
      cout << "YES" << endl;
      return 0;
    }
  }
  cout << "NO" << endl;
}
