#include <bits/stdc++.h>
using namespace std;

#define for_(i,a,b) for(int i=(a);i<(b);++i)
#define for_rev(i,a,b) for(int i=(a);i>=(b);--i)
#define allof(a) (a).begin(),(a).end()
#define minit(a,b) memset(a,b,sizeof(a))
#define size_of(a) int((a).size())
#define cauto const auto

typedef pair< int, int > pii;
template< typename T > using Vec = vector< T >;

class StronglyConnectedComponentDecomposition {
public:
	struct Result {
		Vec< int > topol;
		Vec< Vec< int > > dag;
	};
	
private:
	int N;
	const Vec< Vec< int > >& adj;
	Vec< Vec< int > > rev_adj;
	
	Vec< int > rev_order;
	Vec< bool > used;	
	Vec< int > topol;
	
	void dfs(int v) {
		used[v] = true;
		for (int u : adj[v]) if (!used[u]) dfs(u);
		rev_order.push_back(v);
	}
	
	void revDfs(int v, int k) {
		used[v] = true;
		topol[v] = k;
		for (int u : rev_adj[v]) if (!used[u]) revDfs(u, k);
	}
	
public:
	StronglyConnectedComponentDecomposition(const Vec< Vec< int > >& _adj_) : N(_adj_.size()), adj(_adj_) {
		rev_adj.assign(N, Vec< int >());
		for_(v,0,N) for (int u : adj[v]) rev_adj[u].push_back(v);
	}
	
	Result decomposition() {
		used.assign(N, false);
		rev_order.clear();
		topol.assign(N, -1);
		
		for_(v,0,N) if (!used[v]) dfs(v);
		
		fill(allof(used), false);
		
		int k = 0, m = rev_order.size();
		
		for_rev(i,m-1,0) {
			int v = rev_order[i];
			if (!used[v]) revDfs(v, k++);
		}
		
		Vec< Vec< int > > dag(k);
		
		for_(v,0,N) {
			int tv = topol[v];
			
			for (int u : adj[v]) {
				int tu = topol[u];
				if (tv != tu) dag[tv].push_back(tu);
			}
		}
		
		for_(i,0,k) {
			sort(allof(dag[i]));
			dag[i].erase(unique(allof(dag[i])), dag[i].end());
		}
		
		return Result{ topol, dag };
	}
};

class FindBridge {
private:
	int V;
	Vec< set< int > > adj;
	
	Vec< int > low, pre;
	Vec< bool > vis;
	
	int dfs(int v, int& count, int p, Vec< pii >& br) {
		pre[v] = count++;
		low[v] = pre[v];
		vis[v] = true;
		
		for (int u : adj[v]) {
			if (pre[u] == -1) {
				low[v] = min(low[v], dfs(u, count, v, br));
				if (low[u] == pre[u]) br.push_back(pii(v, u));
			} else {
				if (u != p) low[v] = min(low[v], low[u]);
			}
		}
		
		return low[v];
	}
	
public:
	FindBridge(int V__) : V(V__), adj(V__, set< int >()) {}
	
	void addEdge(int u, int v) {
		adj[u].insert(v);
		adj[v].insert(u);
	}
	
	Vec< pii > get() {
		Vec< pii > br;
		low.assign(V, -1);
		pre.assign(V, -1);
		vis.assign(V, false);
		int count = 0;
		for_(v,0,V) if (!vis[v]) dfs(0, count, -1, br);
		return br;
	}
	
	int count() {
		Vec< pii > br;
		low.assign(V, -1);
		pre.assign(V, -1);
		vis.assign(V, false);
		int count = 0;
		for_(v,0,V) if (!vis[v]) dfs(0, count, -1, br);
		return br.size();
	}
};

int N, M, a[1010], b[1010];
bool isbr[1010];
Vec< Vec< int > > adj;

typedef StronglyConnectedComponentDecomposition SCC;

int doSCC() {	
	SCC::Result scc = SCC(adj).decomposition();
	Vec< int > vcnt(N, 0);
	for_(v,0,N) vcnt[scc.topol[v]]++;
	int szov2 = 0;
	for_(i,0,N) if (vcnt[i] >= 2) szov2++;
	return szov2;
}

void findBr() {
	FindBridge fb(N);
	for_(i,0,M) fb.addEdge(a[i], b[i]);
	Vec< pii > vp = fb.get();
	
	for (pii p : vp) {
		for_(i,0,M) {
			if (p.first == a[i] && p.second == b[i]) isbr[i] = true;
			if (p.first == b[i] && p.second == a[i]) isbr[i] = true;
		}
	}
}

void solve() {
	findBr();
	
	for_(ig,0,M) {
		if (isbr[ig]) continue;
		adj.assign(N, Vec< int >());
		
		for_(i,0,M) {
			if (i == ig) continue;
			adj[a[i]].push_back(b[i]);
		}
		
		if (doSCC() == 0) {
			FindBridge fb(N);

			for_(i,0,M) {
				if (i == ig) continue;
				fb.addEdge(a[i], b[i]);
			}
			
			if (fb.count() >= 2) {
				puts("YES");
				exit(0);
			}
		}
	}
	
	puts("NO");
}

int main() {
	cin >> N >> M;
	for_(i,0,M) {
		cin >> a[i] >> b[i];
		--a[i]; --b[i];
	}
	solve();
}

Measured memory_bytes: 3300