#include <bits/stdc++.h>

#ifdef NON_SUBMIT
#define TEST(n) (n)
#else
#define TEST(n) ((void)0)
#endif

using namespace std;

int color[40], deg[40], ideg[1000000], odeg[1000000];
bool visited[1000000], ovisited[20];
vector<int> adj[1000000], in, on, sadj[20];

void dfs(int c)
{
	visited[c] = true;
	for (auto n : adj[c]) {
		if (!visited[n]) dfs(n);
	}
}

int find_(int a)
{
	if (a == color[a]) return a;
	return color[a] = find_(color[a]);
}

void union_(int a, int b)
{
	a = find_(a);
	b = find_(b);
	color[a] = color[b] = min(a, b);
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	TEST(freopen("input.txt", "r", stdin));
	TEST(freopen("output.txt", "w", stdout));
	int N, M;
	for (cin >> N >> M; M; M--) {
		int a, b;
		cin >> a >> b;
		adj[--a].push_back(--b);
		odeg[a]++;
		ideg[b]++;
	}
	for (int i = 0; i < N; i++) {
		if (ideg[i] == 0) in.push_back(i);
		if (odeg[i] == 0) on.push_back(i);
	}
	for (int i = 0; i < in.size() + on.size(); i++) {
		color[i] = i;
	}
	for (int i = 0; i < in.size(); i++) {
		memset(visited, 0, sizeof(visited));
		dfs(in[i]);
		for (int j = 0; j < on.size(); j++) {
			if (visited[on[j]]) {
			    sadj[i].push_back(j);
			}
		}
	}
	for (int i = 1; i < (1 << in.size()); i++) {
	    int icnt = 0, ocnt = 0;
	    memset(ovisited, 0, sizeof(ovisited));
	    for (int j = 0; j < in.size(); j++) {
	        if(i & (1 << j)) {
	            icnt++;
	            for(auto n: sadj[j]) {
	                ovisited[n] = true;
	            }
	        }
	    }
	    for (int j = 0; j < on.size(); j++) {
	        ocnt += ovisited[j];
	    }
	    if(icnt > ocnt) {
	        cout << "NO\n";
	        return 0;
	    }
	}
	cout << "YES\n";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef vector<int> Vi;
typedef vector<vector<int> > Vvi;

Vvi graph;
Vvi hparg;

int matrix [21];

const int MAXN = 1e6+1;
int nrToSource [MAXN];
int nrToSink [MAXN];
int sourceToNr [MAXN];
int sinkToNr [MAXN];

Vi visited;

void dfs(int cur,int start){
    visited[cur] = true;
    if(nrToSink[cur] != -1)
        matrix[nrToSource[start]] += (1<<nrToSink[cur]);
    for(auto a:graph[cur])
        if(visited[a] == false)
            dfs(a,start);
 }

int main(){
    ios::sync_with_stdio(false);
    int n,m;
    cin >> n >> m;

    visited.resize(n);
    graph.resize(n);
    hparg.resize(n);

    for(int i=0;i<m;i++){
        int a,b;
        cin >> a >> b;
        graph[a-1].push_back(b-1);
        hparg[b-1].push_back(a-1);
    }

    int sinkct = 0,sourcect = 0;
    for(int i=0;i<n;i++){
        if(graph[i].size() == 0){
           // cout<<i+1<<" is sink"<<endl;
            sinkToNr[sinkct] = i;
            nrToSink[i] = sinkct++;
        }
        else
            nrToSink[i] = -1;

        if(hparg[i].size() == 0){
          //  cout<<i+1<<" is source"<<endl;
            sourceToNr[sourcect] = i;
            nrToSource[i] = sourcect++;
        }
        else
            nrToSource[i] = -1;
    }

    for(int i=0;i<sourcect;i++){
        visited.clear();
        visited.resize(n);
        dfs(sourceToNr[i],sourceToNr[i]);
        //cout<<"p "<<matrix[i]<<endl;
    }
    bitset<22> bs(1);
    while(bs.count() < sourcect){
        int mask = 0;

        for(int i=0;i<sourcect;i++)
            if(bs[i])
                mask |= matrix[i];
        if(__builtin_popcount(mask) <= bs.count()){
            cout<<"NO\n";
            exit(0);
        }
        //cout<<bs.to_string()<<endl;
        bs = bitset<22>(bs.to_ulong()+1);
    }
    cout<<"YES\n";

}


#include <bits/stdc++.h>
#define FOR(i, n) for(int i = 0; i < (n); ++i)
#define REP(i, a, b) for(int i = (a); i < (b); ++i)
#define TRAV(i, n) for(auto &i : n)
#define SZ(x) (int)(x).size()
#define PR std::pair
#define MP std::make_pair
#define X first
#define Y second
typedef long long ll;
typedef std::pair<int, int> PII;
typedef std::vector<int> VI;

int n, m;
std::vector<VI> g;
VI src, snk, degin;
int rch[22];
std::vector<bool> rchvec;

void dfs(int v){
	rchvec[v] = true;
	TRAV(ch, g[v]) dfs(ch);
}

int main(){
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cin >> n >> m;
	g.resize(n);
	degin.resize(n);
	FOR(i, m){
		int a, b;
		std::cin >> a >> b;
		g[--a].push_back(--b);
		degin[b]++;
	}
	FOR(i, n){
		if(degin[i] == 0) src.push_back(i);
		if(SZ(g[i]) == 0) snk.push_back(i);
	}
	rchvec.resize(n);
	FOR(i, SZ(src)){
		dfs(src[i]);
		FOR(j, SZ(snk)) if(rchvec[snk[j]]) rch[i] |= 1<<j;
		std::fill(rchvec.begin(), rchvec.end(), false);
	}
	REP(i, 1, (1<<SZ(src))-1){
		int have = 0;
		int cur = i;
		int j = 0;
		while(cur > 0){
			if(cur&1) have |= rch[j];
			j++;
			cur >>= 1;
		}
		if(__builtin_popcount(i) >= __builtin_popcount(have)){
			std::cout << "NO\n";
			return 0;
		}
	}
	std::cout << "YES\n";
	return 0;
}


#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

int n, m, degin[1001005];
vector<int> gg[1001005];
vector<int> source, target;
int p[20], g[20], ses, k, u[1001005];

void dfs(int v) {
    if (u[v] == ses) return;
    u[v] = ses;
    for (int to : gg[v])
        dfs(to);
}

int main() {
    ios_base::sync_with_stdio(false);

    cin >> n >> m;
    while (m--) {
        int x, y;
        cin >> x >> y;
        gg[x].push_back(y);
        ++degin[y];
    }
    for (int i = 1; i <= n; ++i) {
        if (degin[i] == 0)
            source.push_back(i);
        if (gg[i].size() == 0)
            target.push_back(i);
    }
    k = source.size();
    if (k != target.size())
        throw;
    for (int i = 0; i < k; ++i) {
        ++ses;
        dfs(source[i]);
        for (int j = 0; j < k; ++j)
            if (u[target[j]] == ses)
                g[i] |= (1 << j);
    }

    for (int mask = (1 << k) - 1; --mask; ) {
        int cur = 0;
        for (int i = 0; i < k; ++i)
            if ((mask >> i) & 1)
                cur |= g[i];
        if (__builtin_popcount(cur) == __builtin_popcount(mask)) {
            cout << "NO" << endl;
            exit(0);
        }
    }
    cout << "YES" << endl;
}


#ifndef LIB_IO_H
#define LIB_IO_H

#include <iostream>
#include <vector>

namespace io {

template<class U, class V>
std::istream& operator>>(std::istream& is, std::pair<U, V> & p) {
    return is >> p.first >> p.second;
}

template<class T, class I>
auto read_vector(I n) {
    std::vector<T> result(n);
    for (I i = 0; i < n; i++) {
        std::cin >> result[i];
    }
    return result;
}

template<class T>
auto read() {
    T result;
    std::cin >> result;
    return result;
}

}

#endif
#include <queue>
#include <bitset>
#include <iterator>
#include <cassert>
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>

using namespace std;

int main(int argc, char const* argv[]) {
    std::ios_base::sync_with_stdio(false);
    auto n = io::read<int>();
    auto m = io::read<int>();
    vector<vector<int>> g(n);
    vector<vector<int>> gr(n);
    vector<int> out_deg(n);
    for (int i = 0; i < m; i++) {
        auto u = io::read<int>() - 1;
        auto v = io::read<int>() - 1;
        g[u].push_back(v);
        out_deg[u]++;
        gr[v].push_back(u);
    }

    vector<uint32_t> mask(n);
    queue<int> q{};
    auto k = 0;
    for (auto i = 0; i < n; i++) {
        if (out_deg[i] == 0) {
            q.push(i);
            mask[i] = 1 << k++;
        }
    }
    vector<uint32_t> ss{};
    while (!q.empty()) {
        auto u = q.front();
        q.pop();
        for (auto v : g[u]) {
            mask[u] |= mask[v];
        }
        if (gr[u].empty()) {
            ss.push_back(mask[u]);
        } else {
            for (auto v : gr[u]) {
                out_deg[v]--;
                if (out_deg[v] == 0) {
                    q.push(v);
                }
            }
        }
    }

    vector<uint32_t> all_masks(1 << k);

    for (int i = 0; i < k; i++) {
        for (uint32_t m = 0; m < (1 << i); m++) {
            all_masks[m | (1 << i)] = all_masks[m] | ss[i];
        }
    }
    for (uint32_t m = 1; m < (1 << k); m++) {
        if (bitset<20>(all_masks[m]).count() <= bitset<20>(m).count() && m != (1 << k) - 1) {
            cout << "NO\n";
            return 0;
        }
    }

    cout << "YES\n";
}


// >>> TEMPLATES
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using i32 = int32_t;
using i64 = int64_t;
using u32 = uint32_t;
using u64 = uint64_t;
#define int ll
#define double ld
#define rep(i,n) for (int i = 0; i < (int)(n); i++)
#define rep1(i,n) for (int i = 1; i <= (int)(n); i++)
#define repR(i,n) for (int i = (int)(n)-1; i >= 0; i--)
#define rep1R(i,n) for (int i = (int)(n); i >= 1; i--)
#define loop(i,a,B) for (int i = a; i B; i++)
#define loopR(i,a,B) for (int i = a; i B; i--)
#define all(x) begin(x), end(x)
#define allR(x) rbegin(x), rend(x)
#define rng(x,l,r) begin(x) + (l), begin(x) + (r)
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fst first
#define snd second
template <class Int> auto constexpr inf = numeric_limits<Int>::max()/2-1;
auto constexpr INF32 = inf<int32_t>;
auto constexpr INF64 = inf<int64_t>;
auto constexpr INF   = inf<int>;
#ifdef LOCAL
#include "debug.hpp"
#else
#define dump(...) (void)(0)
#define say(x) (void)(0)
#define debug if (0)
#endif
template <class T, class Comp> struct pque : priority_queue<T, vector<T>, Comp> {
    vector<T> &data() { return this->c; }
    void clear() { this->c.clear(); }
};
template <class T> using pque_max = pque<T, less<T>>;
template <class T> using pque_min = pque<T, greater<T>>;
template <class T, class = typename T::iterator, enable_if_t<!is_same<T, string>::value, int> = 0>
ostream& operator<<(ostream& os, T const& a) { bool f = true; for (auto const& x : a) os << (f ? "" : " ") << x, f = false; return os; }
template <class T, size_t N, enable_if_t<!is_same<T, char>::value, int> = 0>
ostream& operator<<(ostream& os, const T (&a)[N]) { bool f = true; for (auto const& x : a) os << (f ? "" : " ") << x, f = false; return os; }
template <class T, class = decltype(begin(declval<T&>())), class = typename enable_if<!is_same<T, string>::value>::type>
istream& operator>>(istream& is, T &a) { for (auto& x : a) is >> x; return is; }
template <class T, class S> ostream& operator<<(ostream& os, pair<T,S> const& p) { return os << p.first << " " << p.second; }
template <class T, class S> istream& operator>>(istream& is, pair<T,S>& p) { return is >> p.first >> p.second; }
struct IOSetup { IOSetup() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); } } iosetup;
template <class F> struct FixPoint : private F {
    constexpr FixPoint(F&& f) : F(forward<F>(f)) {}
    template <class... T> constexpr auto operator()(T&&... x) const { return F::operator()(*this, forward<T>(x)...); }
};
struct MakeFixPoint { template <class F> constexpr auto operator|(F&& f) const { return FixPoint<F>(forward<F>(f)); } };
#define MFP MakeFixPoint()|
#define def(name, ...) auto name = MFP [&](auto &&name, __VA_ARGS__)
template <class T, size_t d> struct vec_impl {
    using type = vector<typename vec_impl<T,d-1>::type>;
    template <class... U> static type make_v(size_t n, U&&... x) { return type(n, vec_impl<T,d-1>::make_v(forward<U>(x)...)); }
};
template <class T> struct vec_impl<T,0> { using type = T; static type make_v(T const& x = {}) { return x; } };
template <class T, size_t d = 1> using vec = typename vec_impl<T,d>::type;
template <class T, size_t d = 1, class... Args> auto make_v(Args&&... args) { return vec_impl<T,d>::make_v(forward<Args>(args)...); }
template <class T> void quit(T const& x) { cout << x << endl; exit(0); }
template <class T, class U> constexpr bool chmin(T& x, U const& y) { if (x > y) { x = y; return true; } return false; }
template <class T, class U> constexpr bool chmax(T& x, U const& y) { if (x < y) { x = y; return true; } return false; }
template <class It> constexpr auto sumof(It b, It e) { return accumulate(b, e, typename iterator_traits<It>::value_type{}); }
template <class T> int sz(T const& x) { return x.size(); }
template <class C, class T> int lbd(C const& v, T const& x) { return lower_bound(begin(v), end(v), x)-begin(v); }
template <class C, class T> int ubd(C const& v, T const& x) { return upper_bound(begin(v), end(v), x)-begin(v); }
const int dx[] = { 1,0,-1,0,1,-1,-1,1 };
const int dy[] = { 0,1,0,-1,1,1,-1,-1 };
constexpr int popcnt(ll x) { return __builtin_popcountll(x); }
// [a,b]
template <class Int> Int rand(Int a, Int b) { static mt19937_64 mt{random_device{}()}; return uniform_int_distribution<Int>(a,b)(mt); }
i64 irand(i64 a, i64 b) { return rand<i64>(a,b); }
u64 urand(u64 a, u64 b) { return rand<u64>(a,b); }
// <<<

int32_t main() {
    int n, m; cin >> n >> m;
    vector<vector<int>> g(n);
    vector<int> in_deg(n), out_deg(n);
    rep (i,m) {
        int a, b; cin >> a >> b; --a, --b;
        g[a].eb(b);
        in_deg[b]++;
        out_deg[a]++;
    }

    vector<int> s, t;
    rep (i,n) if (in_deg[i] == 0) s.eb(i);
    rep (i,n) if (out_deg[i] == 0) t.eb(i);
    assert(s.size() == t.size());
    const int k = s.size();
    dump(k, s, t);

    vector<int> a(k);
    rep (i,k) {
        vector<int> used(n);
        def (dfs, int x) -> void {
            if (used[x]) return;
            used[x] = 1;
            for (int y : g[x]) dfs(y);
        };
        dfs(s[i]);
        rep (j,k) if (used[t[j]]) a[i] ^= 1LL<<j;
    }
    dump(a);

    rep (bit,1LL<<k) {
        if (bit == 0) continue;
        if (bit == (1LL<<k)-1) continue;
        int mask = 0;
        rep (i,k) if (bit>>i&1) mask |= a[i];
        mask ^= (1LL<<k)-1;
        if (popcnt(bit) + popcnt(mask) >= k) quit("NO");
    }
    cout << "YES" << endl;

}


#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <string>
#include <tuple>
#include <functional>
#include <cassert>
#include <cmath>
#include <bitset>
#include <unordered_set>
#include <sstream>
#include <iomanip>
#include <array>
#include <numeric>
#include <stack>
#include <random>

using namespace std;

#define LSB(i) ((i) & -(i)) // zeroes all the bits except the least significant one

#define F first
#define S second
#define PB push_back
#define BOOST ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define ALL(i) begin((i)), end((i))

typedef  long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef vector < int > VI;

using LD = long double;
using PLL = pair<LL, LL>;

template <class T>
bool power_2(T v)
{
	static_assert(std::is_integral<T>::value, "type should be integral");
	return v && !(v & (v - 1));
}

template< class T>
istream& operator>>(istream& st, vector<T> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T, size_t N>
istream& operator>>(istream& st, array<T, N> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T>
ostream& operator<<(ostream& st, const vector<T> & container)
{
	for (auto& u : container)
		st << u << '  ';
	return st;
}

template <class T, class U>
istream& operator>>(istream& st, pair<T, U> & p)
{
	st >> p.first >> p.second;
	return st;
}

template <class T, class U>
ostream& operator<<(ostream& st, pair<T, U> p)
{
	st << p.first << ' ' << p.second;
	return st;
}

template<class T, class U, class V>
pair<T, U> operator* (pair<T, U>p, V val)
{
	return{ p.first * val, p.second * val };
}
template<class T, class U, class V>
pair<T, U> operator/ (pair<T, U>p, V val)
{
	return{ p.first / val, p.second / val };
}
template<class T, class U>
pair<T, U> operator- (pair<T, U> a, pair<T, U> b)
{
	return{ a.first - b.first, a.second - b.second };
}
template<class T, class U>
pair<T, U> operator+ (pair<T, U> a, pair<T, U> b)
{
	return{ a.first + b.first, a.second + b.second };
}

template<class T>
T dotProduct(pair < T, T> a, pair < T, T> b)
{
	return a.first*b.first + a.second* b.second;
}

template<class T>
T crossProduct(pair<T, T>a, pair<T, T> b)
{
	return a.first * b.second - a.second * b.first;
}

template<class T>
T lengthPow(pair<T, T> a)
{
	return a.first*a.first + a.second*a.second;
}

template<class T>
LD length(pair<T, T> a)
{
	return sqrt(lengthPow(a));
}

const int N = 1e6+ 7, inf = 1e9 + 7, MOD = 1e9 + 7;
const LL INF = 1e18 + 7;
const int M = 1 << 16;
const long double PI = acos(-1);
const LD eps = 1e-4;

vector<int> g[N];
bitset<N> hasIn, vis, vis2;

int maskID[N];

int dfs(int v)
{
	vis[v] = true;
	vis2[v] = true;
	int res = 0;

	if (maskID[v] != -1)
	{
		res |= 1 << maskID[v];
	}

	for (auto u : g[v])	{

		if (!vis[u])
		{
			res |= dfs(u);
		}
	}

	return res;
}

int main()
{
	BOOST;
	cout << fixed << setprecision(15);

	int n, m;
	cin >> n >> m;

	fill(maskID, maskID + n, -1);

	for (int i = 0; i < m; ++i)
	{
		int a, b;
		cin >> a >> b;
		--a, --b;
		g[a].push_back(b);
		hasIn[b] = 1;
	}

	int id = 0;
	for (int i = 0; i < n; ++i)
	{
		if (g[i].size() == 0)
		{
			maskID[i] = id++;
		}
	}

	vector<int> sources;
	for (int i = 0; i < n; ++i)
	{
		if (!hasIn[i])
		{
			if (maskID[i] != -1)
			{
				cout << "NO";
				return 0;
			}

			int mask = dfs(i);
			sources.push_back(mask);
			vis.reset();
		}
	}

	for (int i = 1; i < (1 << sources.size()); ++i)
	{
		int mask = 0;
		int ile = 0;
		for (int j = 0; j < sources.size(); ++j)
		{
			if (i&(1 << j))
			{
				mask |= sources[j];
				++ile;
			}
		}
		int ile2 = 0;
		while (mask > 0)
		{
			if (mask & 1)
				++ile2;
			mask /= 2;
		}
		if (ile > ile2)
		{
			cout << "NO";
			return 0;
		}
	}
	cout << "YES";
	return 0;

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <string>
#include <tuple>
#include <functional>
#include <cassert>
#include <cmath>
#include <bitset>
#include <unordered_set>
#include <sstream>
#include <iomanip>
#include <array>
#include <numeric>
#include <stack>
#include <random>

using namespace std;

#define LSB(i) ((i) & -(i)) // zeroes all the bits except the least significant one

#define F first
#define S second
#define PB push_back
#define BOOST ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define ALL(i) begin((i)), end((i))

typedef  long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef vector < int > VI;

using LD = long double;
using PLL = pair<LL, LL>;

template <class T>
bool power_2(T v)
{
	static_assert(std::is_integral<T>::value, "type should be integral");
	return v && !(v & (v - 1));
}

template< class T>
istream& operator>>(istream& st, vector<T> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T, size_t N>
istream& operator>>(istream& st, array<T, N> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T>
ostream& operator<<(ostream& st, const vector<T> & container)
{
	for (auto& u : container)
		st << u << '  ';
	return st;
}

template <class T, class U>
istream& operator>>(istream& st, pair<T, U> & p)
{
	st >> p.first >> p.second;
	return st;
}

template <class T, class U>
ostream& operator<<(ostream& st, pair<T, U> p)
{
	st << p.first << ' ' << p.second;
	return st;
}

template<class T, class U, class V>
pair<T, U> operator* (pair<T, U>p, V val)
{
	return{ p.first * val, p.second * val };
}
template<class T, class U, class V>
pair<T, U> operator/ (pair<T, U>p, V val)
{
	return{ p.first / val, p.second / val };
}
template<class T, class U>
pair<T, U> operator- (pair<T, U> a, pair<T, U> b)
{
	return{ a.first - b.first, a.second - b.second };
}
template<class T, class U>
pair<T, U> operator+ (pair<T, U> a, pair<T, U> b)
{
	return{ a.first + b.first, a.second + b.second };
}

template<class T>
T dotProduct(pair < T, T> a, pair < T, T> b)
{
	return a.first*b.first + a.second* b.second;
}

template<class T>
T crossProduct(pair<T, T>a, pair<T, T> b)
{
	return a.first * b.second - a.second * b.first;
}

template<class T>
T lengthPow(pair<T, T> a)
{
	return a.first*a.first + a.second*a.second;
}

template<class T>
LD length(pair<T, T> a)
{
	return sqrt(lengthPow(a));
}

const int N = 1e6+ 7, inf = 1e9 + 7, MOD = 1e9 + 7;
const LL INF = 1e18 + 7;
const int M = 1 << 16;
const long double PI = acos(-1);
const LD eps = 1e-4;

vector<int> g[N];
bitset<N> hasIn, vis;

int maskID[N];

int dfs(int v)
{
	vis[v] = true;
	int res = 0;

	if (maskID[v] != -1)
	{
		res |= 1 << maskID[v];
	}

	for (auto u : g[v])	{

		if (!vis[u])
		{
			res |= dfs(u);
		}
	}

	return res;
}

int main()
{
	BOOST;
	cout << fixed << setprecision(15);

	int n, m;
	cin >> n >> m;

	fill(maskID, maskID + n, -1);

	for (int i = 0; i < m; ++i)
	{
		int a, b;
		cin >> a >> b;
		--a, --b;
		g[a].push_back(b);
		hasIn[b] = 1;
	}

	int id = 0;
	for (int i = 0; i < n; ++i)
	{
		if (g[i].size() == 0)
		{
			maskID[i] = id++;
		}
	}

	vector<int> sources;
	for (int i = 0; i < n; ++i)
	{
		if (!hasIn[i])
		{
			int mask = dfs(i);
			sources.push_back(mask);
			vis.reset();
		}
	}

	for (int i = 1; i < (1 << sources.size()); ++i)
	{
		int mask = 0;
		int ile = 0;
		for (int j = 0; j < sources.size(); ++j)
		{
			if (i&(1 << j))
				mask |= sources[j];
			++ile;
		}
		int ile2 = 0;
		while (mask > 0)
		{
			if (mask & 1)
				++ile2;
			mask /= 2;
		}
		if (ile >= ile2)
		{
			cout << "NO";
			return 0;
		}
	}
	cout << "YES";
	return 0;

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <string>
#include <tuple>
#include <functional>
#include <cassert>
#include <cmath>
#include <bitset>
#include <unordered_set>
#include <sstream>
#include <iomanip>
#include <array>
#include <numeric>
#include <stack>
#include <random>

using namespace std;

#define LSB(i) ((i) & -(i)) // zeroes all the bits except the least significant one

#define F first
#define S second
#define PB push_back
#define BOOST ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define ALL(i) begin((i)), end((i))

typedef  long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef vector < int > VI;

using LD = long double;
using PLL = pair<LL, LL>;

template <class T>
bool power_2(T v)
{
	static_assert(std::is_integral<T>::value, "type should be integral");
	return v && !(v & (v - 1));
}

template< class T>
istream& operator>>(istream& st, vector<T> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T, size_t N>
istream& operator>>(istream& st, array<T, N> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T>
ostream& operator<<(ostream& st, const vector<T> & container)
{
	for (auto& u : container)
		st << u << '  ';
	return st;
}

template <class T, class U>
istream& operator>>(istream& st, pair<T, U> & p)
{
	st >> p.first >> p.second;
	return st;
}

template <class T, class U>
ostream& operator<<(ostream& st, pair<T, U> p)
{
	st << p.first << ' ' << p.second;
	return st;
}

template<class T, class U, class V>
pair<T, U> operator* (pair<T, U>p, V val)
{
	return{ p.first * val, p.second * val };
}
template<class T, class U, class V>
pair<T, U> operator/ (pair<T, U>p, V val)
{
	return{ p.first / val, p.second / val };
}
template<class T, class U>
pair<T, U> operator- (pair<T, U> a, pair<T, U> b)
{
	return{ a.first - b.first, a.second - b.second };
}
template<class T, class U>
pair<T, U> operator+ (pair<T, U> a, pair<T, U> b)
{
	return{ a.first + b.first, a.second + b.second };
}

template<class T>
T dotProduct(pair < T, T> a, pair < T, T> b)
{
	return a.first*b.first + a.second* b.second;
}

template<class T>
T crossProduct(pair<T, T>a, pair<T, T> b)
{
	return a.first * b.second - a.second * b.first;
}

template<class T>
T lengthPow(pair<T, T> a)
{
	return a.first*a.first + a.second*a.second;
}

template<class T>
LD length(pair<T, T> a)
{
	return sqrt(lengthPow(a));
}

const int N = 1e6+ 7, inf = 1e9 + 7, MOD = 1e9 + 7;
const LL INF = 1e18 + 7;
const int M = 1 << 16;
const long double PI = acos(-1);
const LD eps = 1e-4;

vector<int> g[N];
bitset<N> hasIn, vis;

int maskID[N];

int dfs(int v)
{
	vis[v] = true;
	int res = 0;

	if (maskID[v] != -1)
	{
		res |= 1 << maskID[v];
	}

	for (auto u : g[v])	{

		if (!vis[u])
		{
			res |= dfs(u);
		}
	}

	return res;
}

int main()
{
	BOOST;
	cout << fixed << setprecision(15);

	int n, m;
	cin >> n >> m;

	fill(maskID, maskID + n, -1);

	for (int i = 0; i < m; ++i)
	{
		int a, b;
		cin >> a >> b;
		--a, --b;
		g[a].push_back(b);
		hasIn[b] = 1;
	}

	int id = 0;
	for (int i = 0; i < n; ++i)
	{
		if (g[i].size() == 0)
		{
			maskID[i] = id++;
		}
	}

	vector<int> sources;
	for (int i = 0; i < n; ++i)
	{
		if (!hasIn[i])
		{
			int mask = dfs(i);
			sources.push_back(mask);
			vis.reset();
		}
	}

	for (int i = 1; i < (1 << sources.size()); ++i)
	{
		int mask = 0;
		int ile = 0;
		for (int j = 0; j < sources.size(); ++j)
		{
			if (i&(1 << j))
			{
				mask |= sources[j];
				++ile;
			}
		}
		int ile2 = 0;
		while (mask > 0)
		{
			if (mask & 1)
				++ile2;
			mask /= 2;
		}
		if (ile > ile2)
		{
			cout << "NO";
			return 0;
		}
	}
	cout << "YES";
	return 0;

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <string>
#include <tuple>
#include <functional>
#include <cassert>
#include <cmath>
#include <bitset>
#include <unordered_set>
#include <sstream>
#include <iomanip>
#include <array>
#include <numeric>
#include <stack>
#include <random>

using namespace std;

#define LSB(i) ((i) & -(i)) // zeroes all the bits except the least significant one

#define F first
#define S second
#define PB push_back
#define BOOST ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define ALL(i) begin((i)), end((i))

typedef  long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef vector < int > VI;

using LD = long double;
using PLL = pair<LL, LL>;

template <class T>
bool power_2(T v)
{
	static_assert(std::is_integral<T>::value, "type should be integral");
	return v && !(v & (v - 1));
}

template< class T>
istream& operator>>(istream& st, vector<T> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T, size_t N>
istream& operator>>(istream& st, array<T, N> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T>
ostream& operator<<(ostream& st, const vector<T> & container)
{
	for (auto& u : container)
		st << u << '  ';
	return st;
}

template <class T, class U>
istream& operator>>(istream& st, pair<T, U> & p)
{
	st >> p.first >> p.second;
	return st;
}

template <class T, class U>
ostream& operator<<(ostream& st, pair<T, U> p)
{
	st << p.first << ' ' << p.second;
	return st;
}

template<class T, class U, class V>
pair<T, U> operator* (pair<T, U>p, V val)
{
	return{ p.first * val, p.second * val };
}
template<class T, class U, class V>
pair<T, U> operator/ (pair<T, U>p, V val)
{
	return{ p.first / val, p.second / val };
}
template<class T, class U>
pair<T, U> operator- (pair<T, U> a, pair<T, U> b)
{
	return{ a.first - b.first, a.second - b.second };
}
template<class T, class U>
pair<T, U> operator+ (pair<T, U> a, pair<T, U> b)
{
	return{ a.first + b.first, a.second + b.second };
}

template<class T>
T dotProduct(pair < T, T> a, pair < T, T> b)
{
	return a.first*b.first + a.second* b.second;
}

template<class T>
T crossProduct(pair<T, T>a, pair<T, T> b)
{
	return a.first * b.second - a.second * b.first;
}

template<class T>
T lengthPow(pair<T, T> a)
{
	return a.first*a.first + a.second*a.second;
}

template<class T>
LD length(pair<T, T> a)
{
	return sqrt(lengthPow(a));
}

const int N = 1e6+ 7, inf = 1e9 + 7, MOD = 1e9 + 7;
const LL INF = 1e18 + 7;
const int M = 1 << 16;
const long double PI = acos(-1);
const LD eps = 1e-4;

vector<int> g[N];
bitset<N> hasIn, vis, vis2;

int maskID[N];

int dfs(int v)
{
	vis[v] = true;
	vis2[v] = true;
	int res = 0;

	if (maskID[v] != -1)
	{
		res |= 1 << maskID[v];
	}

	for (auto u : g[v])	{

		if (!vis[u])
		{
			res |= dfs(u);
		}
	}

	return res;
}

int main()
{
	BOOST;
	cout << fixed << setprecision(15);

	int n, m;
	cin >> n >> m;

	if (n == 1)
	{
		cout << "YES";
		return 0;
	}

	fill(maskID, maskID + n, -1);

	for (int i = 0; i < m; ++i)
	{
		int a, b;
		cin >> a >> b;
		--a, --b;
		g[a].push_back(b);
		hasIn[b] = 1;
	}

	int id = 0;
	for (int i = 0; i < n; ++i)
	{
		if (g[i].size() == 0)
		{
			maskID[i] = id++;
		}
	}

	vector<int> sources;
	for (int i = 0; i < n; ++i)
	{
		if (!hasIn[i])
		{
			if (maskID[i] != -1)
			{
				cout << "NO";
				return 0;
			}

			int mask = dfs(i);
			sources.push_back(mask);
			vis.reset();
		}
	}

	for (int i = 1; i < (1 << sources.size())-1; ++i)
	{
		int mask = 0;
		int ile = 0;
		for (int j = 0; j < sources.size(); ++j)
		{
			if (i&(1 << j))
			{
				mask |= sources[j];
				++ile;
			}
		}
		int ile2 = 0;
		while (mask > 0)
		{
			if (mask & 1)
				++ile2;
			mask /= 2;
		}
		if (ile >= ile2)
		{
			cout << "NO";
			return 0;
		}
	}
	cout << "YES";
	return 0;

	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <string>
#include <tuple>
#include <functional>
#include <cassert>
#include <cmath>
#include <bitset>
#include <unordered_set>
#include <sstream>
#include <iomanip>
#include <array>
#include <numeric>
#include <stack>
#include <random>

using namespace std;

#define LSB(i) ((i) & -(i)) // zeroes all the bits except the least significant one

#define F first
#define S second
#define PB push_back
#define BOOST ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define ALL(i) begin((i)), end((i))

typedef  long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef vector < int > VI;

using LD = long double;
using PLL = pair<LL, LL>;

template <class T>
bool power_2(T v)
{
	static_assert(std::is_integral<T>::value, "type should be integral");
	return v && !(v & (v - 1));
}

template< class T>
istream& operator>>(istream& st, vector<T> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T, size_t N>
istream& operator>>(istream& st, array<T, N> & container)
{
	for (auto& u : container)
		st >> u;
	return st;
}

template< class T>
ostream& operator<<(ostream& st, const vector<T> & container)
{
	for (auto& u : container)
		st << u << '  ';
	return st;
}

template <class T, class U>
istream& operator>>(istream& st, pair<T, U> & p)
{
	st >> p.first >> p.second;
	return st;
}

template <class T, class U>
ostream& operator<<(ostream& st, pair<T, U> p)
{
	st << p.first << ' ' << p.second;
	return st;
}

template<class T, class U, class V>
pair<T, U> operator* (pair<T, U>p, V val)
{
	return{ p.first * val, p.second * val };
}
template<class T, class U, class V>
pair<T, U> operator/ (pair<T, U>p, V val)
{
	return{ p.first / val, p.second / val };
}
template<class T, class U>
pair<T, U> operator- (pair<T, U> a, pair<T, U> b)
{
	return{ a.first - b.first, a.second - b.second };
}
template<class T, class U>
pair<T, U> operator+ (pair<T, U> a, pair<T, U> b)
{
	return{ a.first + b.first, a.second + b.second };
}

template<class T>
T dotProduct(pair < T, T> a, pair < T, T> b)
{
	return a.first*b.first + a.second* b.second;
}

template<class T>
T crossProduct(pair<T, T>a, pair<T, T> b)
{
	return a.first * b.second - a.second * b.first;
}

template<class T>
T lengthPow(pair<T, T> a)
{
	return a.first*a.first + a.second*a.second;
}

template<class T>
LD length(pair<T, T> a)
{
	return sqrt(lengthPow(a));
}

const int N = 1e6+ 7, inf = 1e9 + 7, MOD = 1e9 + 7;
const LL INF = 1e18 + 7;
const int M = 1 << 16;
const long double PI = acos(-1);
const LD eps = 1e-4;

vector<int> g[N];
bitset<N> hasIn, vis;

int maskID[N];

int dfs(int v)
{
	vis[v] = true;
	int res = 0;

	if (maskID[v] != -1)
	{
		res |= 1 << maskID[v];
	}

	for (auto u : g[v])	{

		if (!vis[u])
		{
			res |= dfs(u);
		}
	}

	return res;
}

int main()
{
	BOOST;
	cout << fixed << setprecision(15);

	int n, m;
	cin >> n >> m;

	fill(maskID, maskID + n, -1);

	for (int i = 0; i < m; ++i)
	{
		int a, b;
		cin >> a >> b;
		--a, --b;
		g[a].push_back(b);
		hasIn[b] = 1;
	}

	int id = 0;
	for (int i = 0; i < n; ++i)
	{
		if (g[i].size() == 0)
		{
			maskID[i] = id++;
		}
	}

	vector<int> sources;
	for (int i = 0; i < n; ++i)
	{
		if (!hasIn[i])
		{
			int mask = dfs(i);
			sources.push_back(mask);
			vis.reset();
		}
	}

	for (int i = 1; i < (1 << sources.size()); ++i)
	{
		int mask = 0;
		int ile = 0;
		for (int j = 0; j < sources.size(); ++j)
		{
			if (i&(1 << j))
				mask |= sources[j];
			++ile;
		}
		int ile2 = 0;
		while (mask > 0)
		{
			if (mask & 1)
				++ile2;
			mask /= 2;
		}
		if (ile > ile2)
		{
			cout << "NO";
			return 0;
		}
	}
	cout << "YES";
	return 0;

	return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

using namespace __gnu_pbds;
using namespace std;

template<typename T>
struct seti : public tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update> {
	seti(): tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>() {}
	explicit seti(initializer_list<T> o): tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>() {
		for (const T &x : o)
			this->insert(x);
	}
	inline T operator[](int i) {
		return *this->find_by_order(i);
	}
};

int VERY_RANDOM_NUMBER = (uint64_t)(std::make_unique<char>().get()) ^ (uint64_t)(std::chrono::high_resolution_clock::now().time_since_epoch().count());

struct chash {
	inline int operator()(int x) const {
		return x ^ VERY_RANDOM_NUMBER;
	}
};

template <class A, class B>
using hash_table = gp_hash_table<A, B, chash>;

#ifdef LOCAL
template<typename T>
ostream &operator<<(ostream &out, const vector<T> &arr) {
	out << "[";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "]";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const map<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x.first << " => " << x.second;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const multimap<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x.first << " => " << x.second;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const set<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const multiset<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T>
ostream &operator<<(ostream &out, const seti<T> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "}";
	return out;
}

#define debug(...) __debugg(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __debuggg(Arg1 &&arg1) {
	cout << " : " << arg1;
}

void __debuggg([[gnu::unused]] const char *arg1) { }

template <typename Arg1>
void __debugg(const char *name, Arg1 &&arg1) {
	cout << name;
	__debuggg(arg1);
	cout << std::endl;
}

template <typename Arg1, typename... Args>
void __debugg(const char *names, Arg1 &&arg1, Args &&... args) {
	const char *comma = names;
	int gyl = 0;

	while (*comma != ',' or gyl > 0) {
		if (*comma == '(' or * comma == '{' or * comma == '[')
			gyl++;

		if (*comma == ')' or * comma == '}' or * comma == ']')
			gyl--;

		comma++;
	}

	cout.write(names, comma - names);
	__debuggg(arg1);
	cout << " | ";

	if (*(comma + 1) == ' ')
		comma++;

	__debugg(comma + 1, args...);
}
#else
#define debug(...)
#endif

template<typename X, typename Y>
struct Pair {
	X x;
	Y y;
	template<typename X1, typename Y1>
	Pair(const X1 &x, const Y1 &y): x(x), y(y) {}
	Pair() {}
	template<typename X1>
	explicit Pair(const X1 &x): x(x), y(Y()) {}
	template<typename X1, typename Y1>
	Pair<X, Y> operator+(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x + o.x, y + o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator-(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x - o.x, y - o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator*(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x * o.x, y * o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator/(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x / o.x, y / o.y);
	}
	template<typename X1, typename Y1>
	void operator+=(const Pair<X1, Y1> &o) {
		x += o.x;
		y += o.y;
	}
	template<typename X1, typename Y1>
	void operator-=(const Pair<X1, Y1> &o) {
		x -= o.x;
		y -= o.y;
	}
	template<typename X1, typename Y1>
	void operator*=(const Pair<X1, Y1> &o) {
		x *= o.x;
		y *= o.y;
	}
	template<typename X1, typename Y1>
	void operator/=(const Pair<X1, Y1> &o) {
		x /= o.x;
		y /= o.y;
	}
	template<typename X1, typename Y1>
	bool operator<(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y < o.y;

		return x < o.x;
	}
	template<typename X1, typename Y1>
	bool operator<=(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y <= o.y;

		return x <= o.x;
	}
	template<typename X1, typename Y1>
	bool operator>(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y > o.y;

		return x > o.x;
	}
	template<typename X1, typename Y1>
	bool operator>=(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y >= o.y;

		return x >= o.x;
	}
	template<typename X1, typename Y1>
	bool operator==(const Pair<X1, Y1> &o)const {
		return x == o.x and y == o.y;
	}
	template<typename X1, typename Y1>
	bool operator!=(const Pair<X1, Y1> &o)const {
		return x != o.x or y != o.y;
	}
	template<typename X1, typename Y1>
	void swap(Pair<X1, Y1> &o) {
		swap(x, o.x);
		swap(y, o.y);
	}
};

template<typename X, typename Y>
Pair<X, Y> makep(const X &x, const Y &y) {
	return Pair<X, Y>(x, y);
}

template<typename X, typename Y>
ostream &operator<<(ostream &out, const Pair<X, Y> &p) {
	out << "(" << p.x << ", " << p.y << ")";
	return out;
}

template<typename X, typename Y>
istream &operator>>(istream &in, Pair<X, Y> &p) {
	in >> p.x >> p.y;
	return in;
}

#define pair Pair

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef Pair<int, int> pii;
typedef Pair<ll, ll> pll;
typedef vector<pll> vpll;

template<typename T>
istream &operator>>(istream &in, vector<T> &arr) {
	for (auto && x : arr) {
		in >> x;
	}

	return in;
}

template<typename X, typename Y>
inline X mini(X &a, const Y &b) __attribute__((always_inline));
template<typename X, typename Y>
inline X mini(X &a, const Y &b) {
	if (a > b)
		a = b;

	return a;
}
template<typename X, typename Y>
inline X maxi(X &a, const Y &b) __attribute__((always_inline));
template<typename X, typename Y>
inline X maxi(X &a, const Y &b) {
	if (a < b)
		a = b;

	return a;
}

/*link https://codeforces.com/group/8rU0UX1QW3/contest/249177/problem/H */
/*input
3 1
1 2
*/
/*output
NO
*/
/*input
3 3
1 2
1 3
2 3
*/
/*output
YES
*/
/*input
4 4
1 2
1 3
4 2
4 3
*/
/*output
YES
*/

int main () {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n, m;
	cin >> n >> m;
	int out[n] = {}, in[n] = {};
	vi gra[n];
	vi gra2[n];

	for (int i = 0; i < m; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		gra[a].push_back(b);
		gra2[a].push_back(b);
		gra2[b].push_back(a);
		in[b]++;
		out[a]++;
	}

	queue<int> eil;
	vector<bool> apl(n, false);
	int kiekapl = 1;
	eil.push(0);
	apl[0] = true;

	while (!eil.empty()) {
		int dab = eil.front();
		eil.pop();

		for (auto && i : gra2[dab]) {
			if (!apl[i]) {
				eil.push(i);
				apl[i] = true;
				kiekapl++;
			}
		}
	}

	if (kiekapl != n) {
		cout << "NO";
		return 0;
	}

	vi sources, sinks;

	vi kelint(n, -1);

	for (int i = 0; i < n; i++) {
		if (in[i] == 0) {
			sources.push_back(i);
		}

		if (out[i] == 0) {
			kelint[i] = sinks.size();
			sinks.push_back(i);
		}
	}

	int k = sources.size();

	vi pasiekiama(k, 0);

	for (int i = 0; i < k; i++) {
		int s = sources[i];
		queue<int> eil;
		vector<bool> apl(n, false);
		eil.push(s);
		apl[s] = true;

		while (!eil.empty()) {
			int dab = eil.front();
			eil.pop();

			if (kelint[dab] != -1)
				pasiekiama[i] |= (1 << kelint[dab]);

			for (auto && j : gra[dab]) {
				if (!apl[j]) {
					eil.push(j);
					apl[j] = true;
				}
			}
		}
	}

	for (int i = 1; i < (1 << k) - 1; i++) {
		int ma = 0;

		for (int j = 0; j < k; j++) {
			if ((i & (1 << j)) > 0) {
				ma |= pasiekiama[j];
			}
		}

		if (__builtin_popcountll(ma) <= __builtin_popcountll(i)) {
			cout << "NO";
			return 0;
		}
	}

	cout << "YES";
}


//https://codeforces.com/contest/1036/problem/G
#include <iostream>
#include <fstream>
#include <iomanip>
#include <bits/stdc++.h>
#include <chrono>
#include <random>
#include <ext/rope>

using __gnu_cxx::rope;
using std::bitset;
using std::cerr;
using std::deque;
using std::endl;
using std::fill;
using std::ios_base;
using std::istream;
using std::iterator;
using std::make_pair;
using std::map;
using std::max;
using std::min;
using std::numeric_limits;
using std::ostream;
using std::pair;
using std::priority_queue;
using std::set;
using std::sort;
using std::string;
using std::swap;
using std::unordered_map;
using std::vector;

typedef unsigned int ui;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char *name, Arg1 &&arg1)
{
  cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char *names, Arg1 &&arg1, Args &&... args)
{
  const char *comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << ": " << arg1 << " |";
  __f(comma + 1, args...);
}

namespace dalt
{
};
namespace other
{
};

using namespace dalt;

struct Node
{
  vector<int> next;
  bool isSink;
  bool isSrc;
  int id;
};

vector<Node> nodes;

int dfs(int root)
{
  int mask = 0;
  for (int i : nodes[root].next)
  {
    mask |= dfs(i);
  }
  if (nodes[root].isSink)
  {
    mask |= 1 << nodes[root].id;
  }
  return mask;
}

int bitCount(ui i)
{
  i = i - ((i >> 1) & 0x55555555);
  i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
  i = (i + (i >> 4)) & 0x0f0f0f0f;
  i = i + (i >> 8);
  i = i + (i >> 16);
  return i & 0x3f;
}

void solve(istream &in, ostream &out)
{
  int n, m;
  in >> n >> m;
  nodes.resize(n);

  for(int i = 0; i < n; i++){
    nodes[i].isSink = nodes[i].isSrc = true;
  }

  for (int i = 0; i < m; i++)
  {
    int a, b;
    in >> a >> b;
    a--;
    b--;
    nodes[a].next.push_back(b);
    nodes[a].isSink = false;
    nodes[b].isSrc = false;
  }

  int k = 0;
  for (int i = 0; i < n; i++)
  {
    if (nodes[i].isSink)
    {
      nodes[i].id = k++;
    }
  }

  vector<int> masks;
  masks.reserve(k);
  for (int i = 0; i < n; i++)
  {
    if (nodes[i].isSrc)
    {
      masks.push_back(dfs(i));
    }
  }

  vector<int> merged(1 << k);
  for (int i = 1; i < (1 << k); i++)
  {
    for (int j = 0; j < k; j++)
    {
      if ((i >> j) & 1)
      {
        merged[i] |= masks[j];
      }
    }
  }

  for (int i = 1; i < (1 << k) - 1; i++)
  {
    if(bitCount(i) >= bitCount(merged[i]))
    {
      out << "NO" << endl;
      return;
    }
  }

  out << "YES" << endl;
}

int main()
{
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(NULL);
  std::cout << std::setiosflags(std::ios::fixed);
  std::cout << std::setprecision(15);

  solve(std::cin, std::cout);

  return 0;
}


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

typedef long long LL;

const int N=1000000,M=20;

int n,m;
struct side{
  int y,next;
}e[N*2+9];
int lin[N+9],cs;

void Ins(int x,int y){e[++cs].y=y;e[cs].next=lin[x];lin[x]=cs;}

int in[N+9],out[N+9];

void into(){
  scanf("%d%d",&n,&m);
  for (int i=1;i<=m;++i){
	int x,y;
	scanf("%d%d",&x,&y);
	Ins(x,y);
	++in[y];++out[x];
  }
}

int dp[N+9],vis[N+9],c;

int Dfs_dp(int k){
  if (vis[k]) return dp[k];
  vis[k]=1;
  if (!out[k]) dp[k]|=1<<c++;
  for (int i=lin[k];i;i=e[i].next) dp[k]|=Dfs_dp(e[i].y);
  return dp[k];
}

void Get_dp(){
  for (int i=1;i<=n;++i)
	if (!vis[i]) Dfs_dp(i);
}

int to[(1<<M)+9],cnt[(1<<M)+9],ans;

void Get_to(){
  c=0;
  for (int i=1;i<=n;++i)
	if (!in[i]) to[1<<c++]=dp[i];
  ans=1;
  for (int s=0;s<1<<c;++s) cnt[s]=cnt[s>>1]+(s&1);
  for (int s=1;s<1<<c;++s){
	to[s]=to[s&-s]|to[s^s&-s];
	cnt[s]=cnt[s>>1]+(s&1);
	if (cnt[to[s]]<cnt[s]) ans=0;
	if (s^(1<<c)-1&&cnt[to[s]]==cnt[s]) ans=0;
  }
}

void work(){
  Get_dp();
  Get_to();
}

void outo(){
  puts(ans?"YES":"NO");
}

int main(){
  int T=1;
  for (;T--;){
    into();
    work();
    outo();
  }
  return 0;
}


#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MX = 1e6 + 100;
vector<int> G[MX];
int x[MX], y[MX], px = 0, py = 0;
int in[MX];
bitset<30> pp[30];
bitset<MX> pass;
bitset<30> dfs(int n) {
	bitset<30> re;
	if(pass[n]) return re;
	pass[n] = true;
	for(auto it: G[n]) re |= dfs(it);
	if(y[n]) re[y[n]] = true;
	return re;
}
main () {
	int n, m; cin >> n >> m;
	while(m --) {
		int a, b; cin >> a >> b;
		G[a].push_back(b);
		in[b] ++;
	}
	for(int i = 1; i <= n; i ++) {
		if(!in[i]) x[i] = ++px;
		if(G[i].empty()) y[i] = ++py;
	}
	if(px != py) return cout << "NO", 0;
	for(int i = 1; i <= px; i ++) {
		pass.reset();
		pp[x[i]] = dfs(i);
	}
	for(int i = 1; i < (1 << px) - 1; i ++) {
		bitset<30> tmp;
		int cnt = 0;
		for(int j = 0; j < px; j ++) {
			if(i & (1 << j)) {
				tmp |= pp[j + 1];
				cnt ++;
			}
		}
		if(tmp.count() == cnt) return cout << "NO", 0;
	}
	cout << "YES";
}


#include <bits/stdc++.h>
using namespace std;
#define oo 1000000010
#define mod 1000000007
const int N = 1000010;
int n , m , in[N] , u , v , cur[N] , cnt = 0;
vector< int > g[N] , v1;

bool vis[N];

void DFS(int node){
	vis[node] = true;
	for(int i = 0 ;i < (int)g[node].size();i++){
		if(!vis[g[node][i]]) continue;
		cur[node] |= cur[g[node][i]];
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i = 0 ;i < m;i++){
		scanf("%d%d",&u,&v);
		g[u].push_back(v);
		in[v]++;
	}
	for(int i = 1;i<=n;i++){
		if(in[i] == 0)
			v1.push_back(i);
		if((int)g[i].size() == 0){
			cur[i] = (1 << cnt);
			cnt++;
			vis[i] = true;
		}
	}
	for(int i = 1;i<=n;i++){
		if(vis[i] == false)
			DFS(i);
	}
	n = (int)v1.size();
	int tmp = 0 , tmp2 = 0 , tmp3 = 0;
	for(int mask = 1;mask < (1 << n); mask++){
		tmp = tmp2 = tmp3 = 0;
		for(int j = 0 ;j < n;j++){
			if(((mask >> j) & 1) == 1){
				tmp2++;
				tmp |= cur[v1[j]];
			}
		}
		for(int j = 0 ;j < n;j++){
			if(((tmp >> j) & 1) == 1)
				tmp3++;
		}
		if(tmp3 <= tmp2 && tmp2 != n){
			puts("NO");
			return 0;
		}
	}
	puts("YES");
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define oo 1000000010
#define mod 1000000007
const int N = 1000010;
int n , m , in[N] , u , v , cur[N] , cnt = 0;
vector< int > g[N] , v1;

bool vis[N];

void DFS(int node){
	vis[node] = true;
	for(int i = 0 ;i < (int)g[node].size();i++){
		if(!vis[g[node][i]]) DFS(g[node][i]);
		cur[node] |= cur[g[node][i]];
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i = 0 ;i < m;i++){
		scanf("%d%d",&u,&v);
		g[u].push_back(v);
		in[v]++;
	}
	for(int i = 1;i<=n;i++){
		if(in[i] == 0)
			v1.push_back(i);
		if((int)g[i].size() == 0){
			cur[i] = (1 << cnt);
			cnt++;
			vis[i] = true;
		}
	}
	for(int i = 1;i<=n;i++){
		if(vis[i] == false)
			DFS(i);
	}
	n = (int)v1.size();
	assert(cnt == n);
	int tmp = 0 , tmp2 = 0 , tmp3 = 0;
	for(int mask = 1;mask < (1 << n); mask++){
		tmp = tmp2 = tmp3 = 0;
		for(int j = 0 ;j < n;j++){
			if(((mask >> j) & 1) == 1){
				tmp2++;
				tmp |= cur[v1[j]];
			}
		}
		for(int j = 0 ;j < n;j++){
			if(((tmp >> j) & 1) == 1)
				tmp3++;
		}
		if(tmp3 <= tmp2 && tmp2 != n){
			puts("NO");
			return 0;
		}
	}
	puts("YES");
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define oo 1000000010
#define mod 1000000007
const int N = 1000010;
int n , m , in[N] , u , v , cur[N] , cnt = 0;
vector< int > g[N] , v1;

bool vis[N];

void DFS(int node){
	vis[node] = true;
	for(int i = 0 ;i < (int)g[node].size();i++){
		if(!vis[g[node][i]]) continue;
		cur[node] |= cur[g[node][i]];
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i = 0 ;i < m;i++){
		scanf("%d%d",&u,&v);
		g[u].push_back(v);
		in[v]++;
	}
	for(int i = 1;i<=n;i++){
		if(in[i] == 0)
			v1.push_back(i);
		if((int)g[i].size() == 0){
			cur[i] = (1 << cnt);
			cnt++;
			vis[i] = true;
		}
	}
	for(int i = 1;i<=n;i++){
		if(vis[i] == false)
			DFS(i);
	}
	n = (int)v1.size();
	assert(cnt == n);
	int tmp = 0 , tmp2 = 0 , tmp3 = 0;
	for(int mask = 1;mask < (1 << n); mask++){
		tmp = tmp2 = tmp3 = 0;
		for(int j = 0 ;j < n;j++){
			if(((mask >> j) & 1) == 1){
				tmp2++;
				tmp |= cur[v1[j]];
			}
		}
		for(int j = 0 ;j < n;j++){
			if(((tmp >> j) & 1) == 1)
				tmp3++;
		}
		if(tmp3 <= tmp2 && tmp2 != n){
			puts("NO");
			return 0;
		}
	}
	puts("YES");
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define REV(i,j,k) for(int i=j;i>=k;i--)
#define FORR(i,j,k,l) for(int i=j;i<=k;i+=l)
#define inf         freopen("in.txt", "r", stdin)
#define outf        freopen("out.txt", "w", stdout)
#define pf          printf
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c)    scanf("%d %d %d", &a, &b, &c)
#define clean(mat,n)   FOR(i,0,n) mat[i].clear()
#define minn          (long long)-1000000000000000000
#define maxx          (long long) 1000000000000000000
#define mod          1000000007
#define M_PI           3.14159265358979323846  /* pi */
#define LL           long long
#define NL '\n'
#define cnd tree[idx]
#define lnd (idx<<1)
#define rnd ((idx<<1)+1)
#define PB push_back
#define F first
#define S second
#define MAX 1000010
#define MP make_pair
#define valid(nx,ny)  ((nx >= 0) && (nx < row) && (ny >= 0) && (ny < col))
typedef pair<int,int> PR;

int giveId, n, m, id[MAX], vis[MAX], src;
bool in[MAX], out[MAX];
vector<int> con[MAX], mat[MAX];

void dfs(int p)
{
    vis[p] = 1;
    for(auto x: con[p])
    {
        if(vis[x]) continue;
        dfs( x );
    }
}

int getId(int p)
{
    if(id[p] == -1) id[p] = giveId++;
    return id[p];
}

bool ase[22];

int main()
{
    ios::sync_with_stdio(false);
   // inf;

    int u, v;

    cin >> n >> m;
    FOR(i,0,m-1)
    {
        cin >> u >> v;
        con[u].PB( v );
        out[u] = 1; in[v] = 1;
    }

    mem(id, -1);
    FOR(i,1,n)
        if(!in[i]) getId( i ), src++;

    FOR(i,1,n)
        if(!out[i]) getId( i );

    FOR(i,1,n)
        if(!in[i])
        {
            mem(vis, 0);
            dfs( i );

            FOR(j,1,n)
                if(!out[j] && vis[j]) mat[ id[i] ].PB( id[j] );
                   /// cout << id[i] << ' ' << id[j] << endl;
        }

    int ok = 1;

    FOR(i,1,(1<<src)-1)
    {
        FOR(l,0,giveId) ase[l] = 1;

        int l, r;
        l = r = 0;

        FOR(j,0,src-1)
        {
            if(i & (1<<j))
            {
                ///cout << 1;
                r++;
                for(x : mat[ j ])
                {
                    ///cout << "Fuck " << x << endl;
                    l += ase[x];
                    ase[x] = 0;
                }
            }
           /// else cout << 0;
        }
        ///cout << ' ' << l << ' ' << r << endl;
        if(l == src && r == src) continue;
        else if(l <= r) ok = 0;
    }

    if(ok) cout << "YES" << endl;
    else cout << "NO" << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define REV(i,j,k) for(int i=j;i>=k;i--)
#define FORR(i,j,k,l) for(int i=j;i<=k;i+=l)
#define inf         freopen("in.txt", "r", stdin)
#define outf        freopen("out.txt", "w", stdout)
#define pf          printf
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c)    scanf("%d %d %d", &a, &b, &c)
#define clean(mat,n)   FOR(i,0,n) mat[i].clear()
#define minn          (long long)-1000000000000000000
#define maxx          (long long) 1000000000000000000
#define mod          1000000007
#define M_PI           3.14159265358979323846  /* pi */
#define LL           long long
#define NL '\n'
#define cnd tree[idx]
#define lnd (idx<<1)
#define rnd ((idx<<1)+1)
#define PB push_back
#define F first
#define S second
#define MAX 1000010
#define MP make_pair
#define valid(nx,ny)  ((nx >= 0) && (nx < row) && (ny >= 0) && (ny < col))
typedef pair<int,int> PR;

int giveId, n, m, id[MAX], vis[MAX], src;
bool in[MAX], out[MAX];
vector<int> con[MAX], mat[MAX];

void dfs(int p)
{
    vis[p] = 1;
    for(auto x: con[p])
    {
        if(vis[x]) continue;
        dfs( x );
    }
}

int getId(int p)
{
    if(id[p] == -1) id[p] = giveId++;
    return id[p];
}

bool ase[22];

int main()
{
    ios::sync_with_stdio(false);
   // inf;

    int u, v;

    cin >> n >> m;
    FOR(i,0,m-1)
    {
        cin >> u >> v;
        con[u].PB( v );
        out[u] = 1; in[v] = 1;
    }

    mem(id, -1);
    FOR(i,1,n)
        if(!in[i]) getId( i ), src++;

    FOR(i,1,n)
        if(!out[i]) getId( i );

    FOR(i,1,n)
        if(!in[i])
        {
            mem(vis, 0);
            dfs( i );

            FOR(j,1,n)
                if(!out[j] && vis[j]) mat[ id[i] ].PB( id[j] );
                   /// cout << id[i] << ' ' << id[j] << endl;
        }

    int ok = 1;

    FOR(i,1,(1<<src)-1)
    {
        FOR(l,0,giveId) ase[l] = 1;

        int l, r;
        l = r = 0;

        FOR(j,0,src-1)
        {
            if(i & (1<<j))
            {
                ///cout << 1;
                r++;
                for(auto x : mat[ j ])
                {
                    ///cout << "Fuck " << x << endl;
                    l += ase[x];
                    ase[x] = 0;
                }
            }
           /// else cout << 0;
        }
        ///cout << ' ' << l << ' ' << r << endl;
        if(l == src && r == src) continue;
        else if(l <= r) ok = 0;
    }

    if(ok) cout << "YES" << endl;
    else cout << "NO" << endl;

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define REV(i,j,k) for(int i=j;i>=k;i--)
#define FORR(i,j,k,l) for(int i=j;i<=k;i+=l)
#define inf         freopen("in.txt", "r", stdin)
#define outf        freopen("out.txt", "w", stdout)
#define pf          printf
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c)    scanf("%d %d %d", &a, &b, &c)
#define clean(mat,n)   FOR(i,0,n) mat[i].clear()
#define minn          (long long)-1000000000000000000
#define maxx          (long long) 1000000000000000000
#define mod          1000000007
#define M_PI           3.14159265358979323846  /* pi */
#define LL           long long
#define NL '\n'
#define cnd tree[idx]
#define lnd (idx<<1)
#define rnd ((idx<<1)+1)
#define PB push_back
#define F first
#define S second
#define MAX 1000010
#define MP make_pair
#define valid(nx,ny)  ((nx >= 0) && (nx < row) && (ny >= 0) && (ny < col))
typedef pair<int,int> PR;

int giveId, n, m, id[MAX], vis[MAX], src;
bool in[MAX], out[MAX];
vector<int> con[MAX], mat[MAX];

void dfs(int p)
{
    vis[p] = 1;
    for(auto x: con[p])
    {
        if(vis[x]) continue;
        dfs( x );
    }
}

int getId(int p)
{
    if(id[p] == -1) id[p] = giveId++;
    return id[p];
}

bool ase[44];

int main()
{
    ios::sync_with_stdio(false);
   // inf;

    int u, v;

    cin >> n >> m;
    FOR(i,0,m-1)
    {
        cin >> u >> v;
        con[u].PB( v );
        out[u] = 1; in[v] = 1;
    }

    mem(id, -1);
    FOR(i,1,n)
        if(!in[i]) getId( i ), src++;

    FOR(i,1,n)
        if(!out[i]) getId( i );

    FOR(i,1,n)
        if(!in[i])
        {
            mem(vis, 0);
            dfs( i );

            FOR(j,1,n)
                if(!out[j] && vis[j]) mat[ id[i] ].PB( id[j] );
                   /// cout << id[i] << ' ' << id[j] << endl;
        }

    int ok = 1;

    FOR(i,1,(1<<src)-1)
    {
        FOR(l,0,giveId) ase[l] = 1;

        int l, r;
        l = r = 0;

        FOR(j,0,src-1)
        {
            if(i & (1<<j))
            {
                ///cout << 1;
                r++;
                for(auto x : mat[ j ])
                {
                    ///cout << "Fuck " << x << endl;
                    l += ase[x];
                    ase[x] = 0;
                }
            }
           /// else cout << 0;
        }
        ///cout << ' ' << l << ' ' << r << endl;
        if(l == src && r == src) continue;
        else if(l <= r) ok = 0;
    }

    if(ok) cout << "YES" << endl;
    else cout << "NO" << endl;

    return 0;
}


#include <stdio.h>
#include <stack>
#include <map>
#include <string.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <math.h>
#include <vector>
#include <set>
#include <queue>
#include <climits>
#include <unordered_map>
#include <iterator>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ui unsigned int
#define mp make_pair
#define inf32 INT_MAX
#define inf64 LLONG_MAX
#define PI acos(-1)
#define cos45 cos(PI/4)
#define ld long double
#define inf 1000000
#define pii pair<int, int>
#define pll pair<ll, ll>
const int mod = (1e9) + 7;
const double eps = 1e-6;
const int siz = 1e6 + 5, siz2 = 1049659, siz3 = 5032108;
int n, m, cur;
vector<int> to[siz], from[siz], rsnks[siz], srcs;
bool vis[siz];
void dfs(int i) {
	if (from[i].size() == 0) {
		rsnks[cur].push_back(i);
		return;
	}
	for (int tar : from[i]) {
		dfs(tar);
	}
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 0; i < m; i++) {
		int u, v;
		scanf("%d%d", &u, &v);
		to[v].push_back(u);
		from[u].push_back(v);
	}
	int nsrcs = 0;
	for (int i = 1; i <= n; i++) {
		if (to[i].size() == 0) {
			nsrcs++;
			srcs.push_back(i);
			cur = i;
			dfs(i);
		}
	}
	for (int i = 1; i < (1 << nsrcs) - 1; i++) {
		vector<int> cursnks;
		int totsrcs = 0;
		for (int j = 0; j < nsrcs; j++) {
			int mask = 1 << j;
			if (mask & i) {
				totsrcs++;
				for (int snk : rsnks[srcs[j]]) {
					if (!vis[snk]) {
						vis[snk] = true;
						cursnks.push_back(snk);
					}
				}
			}
		}
		if (cursnks.size() == totsrcs) {
			printf("NO\n");
			return 0;
		}
		for (int snk : cursnks) {
			vis[snk] = false;
		}
	}
	printf("YES\n");
	return 0;
}


#include <stdio.h>
#include <stack>
#include <map>
#include <string.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <math.h>
#include <vector>
#include <set>
#include <queue>
#include <climits>
#include <unordered_map>
#include <iterator>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ui unsigned int
#define mp make_pair
#define inf32 INT_MAX
#define inf64 LLONG_MAX
#define PI acos(-1)
#define cos45 cos(PI/4)
#define ld long double
#define inf 1000000
#define pii pair<int, int>
#define pll pair<ll, ll>
const int mod = (1e9) + 7;
const double eps = 1e-6;
const int siz = 1e6 + 5, siz2 = 1049659, siz3 = 5032108;
int n, m, cur;
vector<int> to[siz], from[siz], rsnks[siz], srcs;
bool vis[siz];
void dfs(int i) {
	if (from[i].size() == 0) {
		rsnks[cur].push_back(i);
		return;
	}
	for (int tar : from[i]) {
		dfs(tar);
	}
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 0; i < m; i++) {
		int u, v;
		scanf("%d%d", &u, &v);
		to[v].push_back(u);
		from[u].push_back(v);
	}
	int nsrcs = 0;
	for (int i = 1; i <= n; i++) {
		if (to[i].size() == 0) {
			if (from[i].size() == 0) {
				printf("NO\n");
				return 0;
			}
			nsrcs++;
			srcs.push_back(i);
			cur = i;
			dfs(i);
		}
	}
	for (int i = 1; i < (1 << nsrcs) - 1; i++) {
		vector<int> cursnks;
		int totsrcs = 0;
		for (int j = 0; j < nsrcs; j++) {
			int mask = 1 << j;
			if (mask & i) {
				totsrcs++;
				for (int snk : rsnks[srcs[j]]) {
					if (!vis[snk]) {
						vis[snk] = true;
						cursnks.push_back(snk);
					}
				}
			}
		}
		if (cursnks.size() == totsrcs) {
			printf("NO\n");
			return 0;
		}
		for (int snk : cursnks) {
			vis[snk] = false;
		}
	}
	printf("YES\n");
	return 0;
}


#include <stdio.h>
#include <stack>
#include <map>
#include <string.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <math.h>
#include <vector>
#include <set>
#include <queue>
#include <climits>
#include <unordered_map>
#include <iterator>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ui unsigned int
#define mp make_pair
#define inf32 INT_MAX
#define inf64 LLONG_MAX
#define PI acos(-1)
#define cos45 cos(PI/4)
#define ld long double
#define inf 1000000
#define pii pair<int, int>
#define pll pair<ll, ll>
const int mod = (1e9) + 7;
const double eps = 1e-6;
const int siz = 1e6 + 5, siz2 = 1049659, siz3 = 5032108;
int n, m, tot;
vector<int> to[siz], from[siz];
void dfs(int i) {
	if (from[i].size() == 0) {
		tot++;
		return;
	}
	for (int tar : from[i]) {
		dfs(tar);
	}
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 0; i < m; i++) {
		int u, v;
		scanf("%d%d", &u, &v);
		to[v].push_back(u);
		from[u].push_back(v);
	}
	int srcs = 0, snks = 0;
	for (int i = 1; i <= n; i++) {
		if (to[i].size() == 0) {
			srcs++;
		}
		if (from[i].size() == 0) {
			snks++;
		}
	}
	for (int i = 1; i <= n; i++) {
		if (to[i].size() == 0) {
			dfs(i);
			if (tot < snks) {
				printf("NO\n");
				return 0;
			}
		}
	}
	printf("YES\n");
	return 0;
}


//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <unordered_map>
#include <cassert>

#define prev aakaksnd
#define next aosdalsndl
#define hash asdkalsndasds
#define rank asdaasdasd

using namespace std;

typedef long long ll;
typedef long double dbl;

inline void setmax(int &a, int &b) { if (b > a) a = b; }

template<class T>
void print(vector<T> s){
    for (int i = 0; i < s.size(); i++)
        cout << s[i] << " ";
    cout << endl;
}

const int MAX = 1e6;
int lst[MAX], color[MAX];
vector<int> s[MAX];

int ss[20], mask[MAX];

void dfs(int v, int cur){
	color[v] = 1;
	for (int u : s[v]){
		dfs(u, cur);
		ss[cur] |= mask[u];
	}
}

int main(){
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);/**/
    ios_base::sync_with_stdio(0);
    cin.tie(0);
 	int n, m;
 	cin >> n >> m;
 	for (int i = 0; i < n; i++){
 		int a, b;
 		cin >> a >> b;
 		s[a - 1].push_back(b - 1);
 		lst[b - 1] = 1;
 	}
 	int cur = 0;
 	for (int i = 0; i < n; i++){
 		if (s[i].size() == 0){
 			mask[i] = (1 << cur);
 			cur++;
 		}
 	}
 	cur = 0;
 	for (int i = 0; i < n; i++){
 		if (lst[i] == 0){
 			fill(color, color + n, 0);
 			dfs(i, cur++);
 		}
 	}
 	fill(color, color + n, 0);
 	for (int i = 1; i < (1 << cur) - 1; i++){
 		int cnt1 = 0, cnt2 = 0;
 		int now = 0;
 		for (int j = 0; j < cur; j++){
 			if (i & (1 << j)){
 				cnt1++;
 				now |= ss[j];
 			}
 		}
 		while (now > 0){
 			if (now & 1)
 				cnt2++;
 			now >>= 1;
 		}
 		if (cnt1 >= cnt2){
 			cout << "No" << endl;
 			return 0;
 		}
 	}
 	cout << "Yes" << endl;
    return 0;
}


//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <unordered_map>
#include <cassert>

#define prev aakaksnd
#define next aosdalsndl
#define hash asdkalsndasds
#define rank asdaasdasd

using namespace std;

typedef long long ll;
typedef long double dbl;

template<class T>
void print(vector<T> s){
    for (int i = 0; i < s.size(); i++)
        cout << s[i] << " ";
    cout << endl;
}

const int MAX = 1e6;
int lst[MAX], color[MAX];
vector<int> s[MAX];

int ss[20], mask[MAX];

void dfs(int v, int cur){
	color[v] = 1;
	for (int u : s[v]){
		dfs(u, cur);
		ss[cur] |= mask[u];
	}
}

int main(){
    //freopen("test.in", "r", stdin);
    //freopen("test.out", "w", stdout);/**/
    ios_base::sync_with_stdio(0);
    cin.tie(0);
 	int n, m;
 	cin >> n >> m;
 	for (int i = 0; i < m; i++){
 		int a, b;
 		cin >> a >> b;
 		s[a - 1].push_back(b - 1);
 		lst[b - 1] = 1;
 	}
 	int cur = 0;
 	for (int i = 0; i < n; i++){
 		if (s[i].size() == 0){
 			mask[i] = (1 << cur);
 			cur++;
 		}
 	}
 	cur = 0;
 	for (int i = 0; i < n; i++){
 		if (lst[i] == 0){
 			fill(color, color + n, 0);
 			dfs(i, cur++);
 		}
 	}
 	fill(color, color + n, 0);
 	for (int i = 1; i < (1 << cur) - 1; i++){
 		int cnt1 = 0, cnt2 = 0;
 		int now = 0;
 		for (int j = 0; j < cur; j++){
 			if (i & (1 << j)){
 				cnt1++;
 				now |= ss[j];
 			}
 		}
 		while (now > 0){
 			if (now & 1)
 				cnt2++;
 			now >>= 1;
 		}
 		if (cnt1 >= cnt2){
 			cout << "No" << endl;
 			return 0;
 		}
 	}
 	cout << "Yes" << endl;
    return 0;
}


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

typedef long long ll;
typedef pair<int,int> pii;
#define FOR(i,ii,iii)for(int i=ii;i<iii;i++)
#define RFOR(i,ii,iii)for(int i=iii-1;i>=ii;i--)
#define OUT(a)cout<<a<<endl
#define ALL(s) s.begin(),s.end()
#define PB push_back
#define ANS(a) OUT(res.size());for(auto i:a)cout<<i<<" ";ENDL
#define PRINT(a,init,end) FOR(i,init,end) cout<<a[i]<<" ";ENDL
#define PRINTV(a) for(auto i:a)cout<<i<<" ";ENDL
#define F first
#define S second

const int N=1e6+15;\
vector<int>g[N];
int n,m,pa[N],sz[N];
bool vst[N],notSource[N],sinc[N];
set<int>match[N];
void dfs(int pos,int root) {
  if(vst[pos])return;
  vst[pos]=1;
  if(sinc[pos])match[root].insert(pos);
  for(int i:g[pos])dfs(i,root);
}

int main() {
  ios::sync_with_stdio(false);
  cin>>n>>m;
	FOR(i,0,n) pa[i]=i,sz[i]=1;
  FOR(i,0,m) {
    int a,b;
    cin>>a>>b;
    g[a-1].PB(b-1);
    notSource[b-1]=true;
  }
  vector<int>src;
  FOR(i,0,n) {
    if(!g[i].size())sinc[i]=true;
    if(!notSource[i])src.PB(i);
  }
  for(int i:src)dfs(i,i);
  FOR(i,1,1<<src.size()-1) {
    set<int>ac;
    FOR(j,0,src.size())
      if(i&(1<<j)) {
        for(int k:match[src[j]])ac.insert(k);
      }
    //cout<<"mask: "<<i<<" : "<<ac.size()<<" "<<__builtin_popcount(i)<<endl;
    if(ac.size()<=__builtin_popcount(i))return!(OUT("NO"));
  }
  OUT("YES");
}


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

#define FOR(i,ii,iii)for(int i=ii;i<iii;i++)
#define OUT(a)cout<<a<<endl
#define PB push_back

const int N=1e6+15;
vector<int>g[N];
int n,m;
bool vst[N],notSource[N],sinc[N];
set<int>match[N];
vector<int>src;
void dfs(int pos,int root) {
  if(vst[pos])return;
  vst[pos]=1;
  if(sinc[pos])match[root].insert(pos);
  for(int i:g[pos])dfs(i,root);
}
string toBit(int x) { // print mask
  string s="";
  FOR(i,0,src.size()) if(x&(1<<i))s+='1';else s+='0';
  return s;
}
int main() {
  ios::sync_with_stdio(false);
  cin>>n>>m;
  FOR(i,0,m) {
    int a,b;
    cin>>a>>b;
    g[a-1].PB(b-1);
    notSource[b-1]=true;
  }
  FOR(i,0,n) {
    if(!g[i].size())sinc[i]=true;
    if(!notSource[i])src.PB(i);
  }
  for(int i:src){
    dfs(i,i);
    memset(vst,0,sizeof(vst));
  }
  FOR(i,1,(1<<src.size())-1) {
    set<int>ac;
    FOR(j,0,src.size()) {
      if(i&(1<<j)) {
        for(int k:match[src[j]])ac.insert(k);
      }
    }
    //cout<<"mask: "<<toBit(i)<<" : "<<ac.size()<<" "<<__builtin_popcount(i)<<endl;
    if(ac.size()<=__builtin_popcount(i))return!(OUT("NO"));
  }
  /*
  for(int i:src) {
    cout<<i<<" : ";
    for(int j:match[i])cout<<j<<" ";
    cout<<endl;
  }
  */
  OUT("YES");
}


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

typedef long long ll;
typedef pair<int,int> pii;
#define FOR(i,ii,iii)for(int i=ii;i<iii;i++)
#define RFOR(i,ii,iii)for(int i=iii-1;i>=ii;i--)
#define OUT(a)cout<<a<<endl
#define ALL(s) s.begin(),s.end()
#define PB push_back
#define ANS(a) OUT(res.size());for(auto i:a)cout<<i<<" ";ENDL
#define PRINT(a,init,end) FOR(i,init,end) cout<<a[i]<<" ";ENDL
#define PRINTV(a) for(auto i:a)cout<<i<<" ";ENDL
#define F first
#define S second

const int N=1e6+15;\
vector<int>g[N];
int n,m,pa[N],sz[N];
bool vst[N];
int findPa(int pos){
	if(pa[pos]!=pos)pa[pos]=findPa(pa[pos]);
	return pa[pos];
}
void join(int a, int b) {
	int x=findPa(a),y=findPa(b);
	if (x!=y) {
		if(sz[x]>=sz[y]) sz[x]+=sz[y],pa[y]=x;
		else sz[y]+=sz[x],pa[x]=y;
	}
}

void dfs(int pos) {
  if(vst[pos])return;
  vst[pos]=1;
  for(int i:g[pos]) {
    join(pos,i);
    dfs(i);
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin>>n>>m;
	FOR(i,0,n) pa[i]=i,sz[i]=1;
  FOR(i,0,m) {
    int a,b;
    cin>>a>>b;
    g[a-1].PB(b-1);
  }
  FOR(i,0,n)dfs(i);
  FOR(i,1,n)if(findPa(i)!=findPa(i-1))return!(OUT("NO"));
  OUT("YES");
}


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

#define FOR(i,ii,iii)for(int i=ii;i<iii;i++)
#define OUT(a)cout<<a<<endl
#define PB push_back

const int N=1e6+15;
vector<int>g[N];
int n,m;
bool vst[N],notSource[N],sinc[N];
set<int>match[N];
void dfs(int pos,int root) {
  if(vst[pos])return;
  vst[pos]=1;
  if(sinc[pos])match[root].insert(pos);
  for(int i:g[pos])dfs(i,root);
}

int main() {
  ios::sync_with_stdio(false);
  cin>>n>>m;
  FOR(i,0,m) {
    int a,b;
    cin>>a>>b;
    g[a-1].PB(b-1);
    notSource[b-1]=true;
  }
  vector<int>src;
  FOR(i,0,n) {
    if(!g[i].size())sinc[i]=true;
    if(!notSource[i])src.PB(i);
  }
  for(int i:src){
    dfs(i,i);
    memset(vst,0,sizeof(vst));
  }
  FOR(i,1,1<<src.size()-1) {
    set<int>ac;
    FOR(j,0,src.size()) {
      if(i&(1<<j)) {
        for(int k:match[src[j]])ac.insert(k);
      }
    }
    //cout<<"mask: "<<i<<" : "<<ac.size()<<" "<<__builtin_popcount(i)<<endl;
    if(ac.size()<=__builtin_popcount(i))return!(OUT("NO"));
  }
  OUT("YES");
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<stack>
#include<cassert>
#include<queue>
using namespace std;
#define N 2000020
typedef long long ll;
inline ll read(){
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<1)+(x<<3)+c-'0';
		c=getchar();
	}
	return x*f;
}
int n,m,col[N],num,dfn[N],low[N],x[N],y[N],dp[N],in[N],d[N],vis[N],tot,g[N],o;
vector<int> G[N],T[N];
stack<int> st;
void Tarjan(int u){
	low[u]=dfn[u]=++num;
	st.push(u);
	vis[u]=1;
	for(auto v:G[u]){
		if(!dfn[v]){
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(low[u]==dfn[u]){
		int t=0;
		tot++;
		while(t!=u){
			t=st.top();
			col[t]=tot;
			vis[t]=0;
			st.pop();
		}
	}
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=m;++i){
		int v=read(),u=read();
		G[u].push_back(v);
		x[i]=u,y[i]=v;
		++in[v];
	}
	for(int i=1;i<=n;++i){
		if(!dfn[i])Tarjan(i);
	}
	for(int i=1;i<=m;++i){
		if(col[x[i]]^col[y[i]]){
			T[col[y[i]]].push_back(col[x[i]]);
			++d[col[x[i]]];
		}
	}
	queue<int> q;
	int s=0;
	for(int i=1;i<=n;++i){
		if(G[i].empty()){
			dp[col[i]]|=1<<s;
			++s;
		}
	}
	//cerr<<" ?? "<<s<<endl;
	for(int i=1;i<=tot;++i){
		if(!d[i])q.push(i);
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(auto v:T[u]){
			dp[v]|=dp[u];
			if(!--d[v])q.push(v);
		}
	}
	for(int i=1;i<=tot;++i){
		assert(d[i]==0);
	}
	for(int i=1;i<=n;++i){
		if(!in[i]){
			g[++o]=col[i];
		}
	}
	for(int i=0;i<(1<<s);++i){
		int all=0;
		for(int j=1;j<=s;++j){
			if((i>>j-1)&1){
				all|=dp[j];
			}
		}
		if(__builtin_popcount(i)>__builtin_popcount(all))return !printf("NO\n");
	}
	printf("YES\n");
	return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<stack>
#include<cassert>
#include<queue>
using namespace std;
#define N 200020
typedef long long ll;
inline ll read(){
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<1)+(x<<3)+c-'0';
		c=getchar();
	}
	return x*f;
}
int n,m,col[N],num,dfn[N],low[N],x[N],y[N],dp[N],in[N],d[N],vis[N],tot;
vector<int> G[N],T[N];
stack<int> st;
void Tarjan(int u){
	low[u]=dfn[u]=++num;
	st.push(u);
	vis[u]=1;
	for(auto v:G[u]){
		if(!dfn[v]){
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(low[u]==dfn[u]){
		int t=0;
		tot++;
		while(t!=u){
			t=st.top();
			col[t]=tot;
			vis[t]=0;
			st.pop();
		}
	}
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=m;++i){
		int v=read(),u=read();
		G[u].push_back(v);
		x[i]=u,y[i]=v;
		++in[v];
	}
	for(int i=1;i<=n;++i){
		if(!dfn[i])Tarjan(i);
	}
	for(int i=1;i<=m;++i){
		if(col[x[i]]^col[y[i]]){
			T[col[y[i]]].push_back(col[x[i]]);
			++d[col[x[i]]];
		}
	}
	queue<int> q;
	int s=0;
	for(int i=1;i<=n;++i){
		if(G[i].empty()){
			dp[col[i]]|=1<<s;
			++s;
		}
	}
	for(int i=1;i<=tot;++i){
		if(!d[i])q.push(i);
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(auto v:T[u]){
			dp[v]|=dp[u];
			if(!--d[v])q.push(v);
		}
	}
	for(int i=1;i<=tot;++i){
		assert(d[i]==0);
	}
	for(int i=1;i<=n;++i){
		if(!in[i]){
			if(dp[col[i]]^((1<<s)-1))return !printf("NO\n");
		}
	}
	printf("YES\n");
	return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<stack>
#include<cassert>
#include<queue>
using namespace std;
#define N 2000020
typedef long long ll;
inline ll read(){
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<1)+(x<<3)+c-'0';
		c=getchar();
	}
	return x*f;
}
int n,m,col[N],num,dfn[N],low[N],x[N],y[N],dp[N],in[N],d[N],vis[N],tot,g[N],o;
vector<int> G[N],T[N];
stack<int> st;
void Tarjan(int u){
	low[u]=dfn[u]=++num;
	st.push(u);
	vis[u]=1;
	for(auto v:G[u]){
		if(!dfn[v]){
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(low[u]==dfn[u]){
		int t=0;
		tot++;
		while(t!=u){
			t=st.top();
			col[t]=tot;
			vis[t]=0;
			st.pop();
		}
	}
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=m;++i){
		int v=read(),u=read();
		G[u].push_back(v);
		x[i]=u,y[i]=v;
		++in[v];
	}
	for(int i=1;i<=n;++i){
		if(!dfn[i])Tarjan(i);
	}
	for(int i=1;i<=m;++i){
		if(col[x[i]]^col[y[i]]){
			T[col[y[i]]].push_back(col[x[i]]);
			++d[col[x[i]]];
		}
	}
	queue<int> q;
	int s=0;
	for(int i=1;i<=n;++i){
		if(G[i].empty()){
			dp[col[i]]|=1<<s;
			++s;
		}
	}
	//cerr<<" ?? "<<s<<endl;
	for(int i=1;i<=tot;++i){
		if(!d[i])q.push(i);
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(auto v:T[u]){
			dp[v]|=dp[u];
			if(!--d[v])q.push(v);
		}
	}
	for(int i=1;i<=tot;++i){
		assert(d[i]==0);
	}
	for(int i=1;i<=n;++i){
		if(!in[i]){
			g[++o]=col[i];
		}
	}
	for(int i=1;i<(1<<s)-1;++i){
		int all=0;
		for(int j=1;j<=s;++j){
			if((i>>j-1)&1){
				all|=dp[j];
			}
		}
		if(__builtin_popcount(i)>=__builtin_popcount(all))return !printf("NO\n");
	}
	printf("YES\n");
	return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<stack>
#include<cassert>
#include<queue>
using namespace std;
#define N 2000020
typedef long long ll;
inline ll read(){
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=(x<<1)+(x<<3)+c-'0';
		c=getchar();
	}
	return x*f;
}
int n,m,col[N],num,dfn[N],low[N],x[N],y[N],dp[N],in[N],d[N],vis[N],tot,g[N],o;
vector<int> G[N],T[N];
stack<int> st;
void Tarjan(int u){
	low[u]=dfn[u]=++num;
	st.push(u);
	vis[u]=1;
	for(auto v:G[u]){
		if(!dfn[v]){
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(vis[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(low[u]==dfn[u]){
		int t=0;
		tot++;
		while(t!=u){
			t=st.top();
			col[t]=tot;
			vis[t]=0;
			st.pop();
		}
	}
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=m;++i){
		int v=read(),u=read();
		G[u].push_back(v);
		x[i]=u,y[i]=v;
		++in[v];
	}
	for(int i=1;i<=n;++i){
		if(!dfn[i])Tarjan(i);
	}
	for(int i=1;i<=m;++i){
		if(col[x[i]]^col[y[i]]){
			T[col[y[i]]].push_back(col[x[i]]);
			++d[col[x[i]]];
		}
	}
	queue<int> q;
	int s=0;
	for(int i=1;i<=n;++i){
		if(G[i].empty()){
			dp[col[i]]|=1<<s;
			++s;
		}
	}
	//cerr<<" ?? "<<s<<endl;
	for(int i=1;i<=tot;++i){
		if(!d[i])q.push(i);
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(auto v:T[u]){
			dp[v]|=dp[u];
			if(!--d[v])q.push(v);
		}
	}
	for(int i=1;i<=tot;++i){
		assert(d[i]==0);
	}
	for(int i=1;i<=n;++i){
		if(!in[i]){
			g[++o]=col[i];
		}
	}
	for(int i=1;i<(1<<s)-1;++i){
		int all=0;
		for(int j=1;j<=s;++j){
			if((i>>j-1)&1){
				all|=dp[g[j]];
			}
		}
		if(__builtin_popcount(i)>=__builtin_popcount(all))return !printf("NO\n");
	}
	printf("YES\n");
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
vector < int > used;
vector < vector < int > > g;

void dfs(int x){
    if (used[x])return;
    used[x] = 1;
    for (auto y : g[x]) dfs(y);
}
int main()
{

    int n, m;
    cin >> n >> m;
    used.resize(n);
    vector < int > in(n), out(n);
    g.resize(n, vector < int > ());
    for (int i = 0; i < m; i++){
        int v, u;
        cin >> v >> u;
        --v;
        --u;
        in[u]++;
        out[v]++;
        g[v].push_back(u);
    }

    vector < int > s;
    vector < int > t;

    for (int i = 0; i < n; i++){
        if (in[i] == 0)
            s.push_back(i);
        if(out[i] == 0)
            t.push_back(i);
    }
    vector < int > r(s.size(), 0);

    for (int i = 0; i < s.size(); i++){
        fill(used.begin(), used.end(), 0);

        dfs(s[i]);

        for (int j = 0; j < t.size(); j++){
            if(used[t[j]])
                r[i] ^= (1 << j);
        }
    }

    for (int mask = 1; mask < (1 << s.size()) - 1; mask++){
            int res = 0;
        for (int j = 0; j < s.size(); j++)
        {
            if (mask & (1 << j)){
                res |= r[j];
            }
        }
        //cout << mask << " " << __builtin_popcount(mask) << " " << res << " " << __builtin_popcount(res) << endl;
        if (__builtin_popcount(mask) >= __builtin_popcount(res))
        {
            cout << "NO";
            return 0;
        }
    }
    cout << "YES";
    return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cassert>

std::vector<int> dag[1000000];
int in[1000000];
int snk_id[1000000];

bool vis[1000000];

std::vector<int> adj[40];
int srcs=0,snks=0;
int match[40];

std::vector<int> mini[20];

void dfs_vis(int x){
  vis[x]=true;
  for(int y:dag[x]){
    if(!vis[y]){
      dfs_vis(y);
    }
  }
}

bool dfs_match(int x){
  if(vis[x]) return false;
  vis[x]=true;
  for(int y:adj[x]){
    if(match[y]==-1||dfs_match(match[y])){
      match[y]=x;
      match[x]=y;
      return true;
    }
  }
  return false;
}

void dfs_mini(int x){
  vis[x]=true;
  for(int y:mini[x]){
    if(!vis[y]){
      dfs_mini(y);
    }
  }
}

int main(){
  int N,M;
  scanf("%d %d",&N,&M);
  for(int i=0;i<M;i++){
    int U,V;
    scanf("%d %d",&U,&V);
    U--,V--;
    dag[U].push_back(V);
    in[V]++;
  }
  std::fill(snk_id,snk_id+N,-1);
  for(int x=0;x<N;x++){
    if(dag[x].empty()){
      snk_id[x]=snks++;
    }
  }
  for(int x=0;x<N;x++){
    if(in[x]==0){
      std::fill(vis,vis+N,false);
      dfs_vis(x);
      for(int y=0;y<N;y++){
	if(vis[y]&&snk_id[y]!=-1){
	  adj[snk_id[y]].push_back(srcs+snks);
	  adj[srcs+snks].push_back(snk_id[y]);
	}
      }
      srcs++;
    }
  }
  if(srcs!=snks){
    printf("NO\n");
    return 0;
  }
  int matching=0;
  std::fill(match,match+srcs+snks,-1);
  for(int i=0;i<snks;i++){
    std::fill(vis,vis+srcs+snks,false);
    matching+=dfs_match(i);
  }
  if(matching!=srcs){
    printf("NO\n");
    return 0;
  }
  for(int i=0;i<snks;i++){
    for(int j:adj[i]){
      mini[i].push_back(match[j]);
    }
  }
  for(int i=0;i<snks;i++){
    std::fill(vis,vis+snks,false);
    dfs_mini(i);
    for(int j=0;j<snks;j++){
      if(!vis[j]){
	printf("NO\n");
	return 0;
      }
    }
  }
  printf("YES\n");
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cassert>

std::vector<int> dag[1000000];
int in[1000000];
int snk_id[1000000];

bool vis[1000000];

std::vector<int> adj[20];
int srcs=0,snks=0;
int match[40];

std::vector<int> mini[20];

void dfs_vis(int x){
  vis[x]=true;
  for(int y:dag[x]){
    if(!vis[y]){
      dfs_vis(y);
    }
  }
}

bool dfs_match(int x){
  if(vis[x]) return false;
  vis[x]=true;
  for(int y:adj[x]){
    if(match[y]==-1||dfs_match(match[y])){
      match[y]=x;
      match[x]=y;
      return true;
    }
  }
  return false;
}

void dfs_mini(int x){
  vis[x]=true;
  for(int y:mini[x]){
    if(!vis[y]){
      dfs_vis(y);
    }
  }
}

int main(){
  int N,M;
  scanf("%d %d",&N,&M);
  for(int i=0;i<M;i++){
    int U,V;
    scanf("%d %d",&U,&V);
    U--,V--;
    dag[U].push_back(V);
    in[V]++;
  }
  std::fill(snk_id,snk_id+N,-1);
  for(int x=0;x<N;x++){
    if(dag[x].empty()){
      snk_id[x]=snks++;
      //printf("SNK %d\n",x);
    }
  }
  for(int x=0;x<N;x++){
    if(in[x]==0){
      std::fill(vis,vis+N,false);
      dfs_vis(x);
      for(int y=0;y<N;y++){
	if(vis[y]&&snk_id[y]!=-1){
	  adj[snk_id[y]].push_back(srcs+snks);
	  adj[srcs+snks].push_back(snk_id[y]);
	  //printf("ADJ %d<=>%d\n",snk_id[y],srcs+snks);
	}
      }
      srcs++;
    }
  }
  //printf("%d,%d\n",srcs,snks);
  if(srcs!=snks){
    printf("NO\n");
    //fprintf(stderr,"srcs!=snks\n");
    return 0;
  }
  /*
  for(int i=0;i<srcs;i++){
    for(int j:adj[i]){
      printf("%d=>%d\n",i,j);
    }
  }
  */
  int matching=0;
  std::fill(match,match+srcs+snks,-1);
  for(int i=0;i<snks;i++){
    std::fill(vis,vis+srcs+snks,false);
    matching+=dfs_match(i);
  }
  //printf("max matching: %d\n",matching);
  if(matching!=srcs){
    printf("NO\n");
    //fprintf(stderr,"not perfect\n");
    return 0;
  }
  for(int i=0;i<snks+srcs;i++){
    //printf("match %d<=>%d\n",i,match[i]);
    assert(match[match[i]]==i);
  }
  for(int i=0;i<snks;i++){
    for(int j:adj[i]){
      mini[i].push_back(match[j]);
      assert(match[match[j]]==j);
      //printf("mini: %d=>(%d)=>%d\n",i,j,match[j]);
    }
  }
  for(int i=0;i<snks;i++){
    std::fill(vis,vis+snks,false);
    dfs_mini(i);
    for(int j=0;j<snks;j++){
      if(!vis[j]){
	printf("NO\n");
	//fprintf(stderr,"not strongly connected\n");
	return 0;
      }
    }
  }
  printf("YES\n");
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cassert>

std::vector<int> dag[1000000];
int in[1000000];
int snk_id[1000000];

bool vis[1000000];

std::vector<int> adj[40];
int srcs=0,snks=0;
int match[40];

std::vector<int> mini[20];

void dfs_vis(int x){
  vis[x]=true;
  for(int y:dag[x]){
    if(!vis[y]){
      dfs_vis(y);
    }
  }
}

bool dfs_match(int x){
  if(vis[x]) return false;
  vis[x]=true;
  for(int y:adj[x]){
    if(match[y]==-1||dfs_match(match[y])){
      match[y]=x;
      match[x]=y;
      return true;
    }
  }
  return false;
}

void dfs_mini(int x){
  vis[x]=true;
  for(int y:mini[x]){
    if(!vis[y]){
      dfs_mini(y);
    }
  }
}

int main(){
  int N,M;
  scanf("%d %d",&N,&M);
  for(int i=0;i<M;i++){
    int U,V;
    scanf("%d %d",&U,&V);
    U--,V--;
    dag[U].push_back(V);
    in[V]++;
  }
  std::fill(snk_id,snk_id+N,-1);
  for(int x=0;x<N;x++){
    if(dag[x].empty()){
      snk_id[x]=snks++;
      //printf("SNK %d\n",x);
    }
  }
  for(int x=0;x<N;x++){
    if(in[x]==0){
      //printf("SRC %d\n",x);
      std::fill(vis,vis+N,false);
      dfs_vis(x);
      for(int y=0;y<N;y++){
	if(vis[y]&&snk_id[y]!=-1){
	  adj[snk_id[y]].push_back(srcs+snks);
	  adj[srcs+snks].push_back(snk_id[y]);
	  //printf("ADJ %d<=>%d\n",snk_id[y],srcs+snks);
	}
      }
      srcs++;
    }
  }
  //printf("%d,%d\n",srcs,snks);
  if(srcs!=snks){
    printf("NO\n");
    //fprintf(stderr,"srcs!=snks\n");
    return 0;
  }
  /*
  for(int i=0;i<srcs;i++){
    for(int j:adj[i]){
      printf("%d=>%d\n",i,j);
    }
  }
  */
  int matching=0;
  std::fill(match,match+srcs+snks,-1);
  for(int i=0;i<snks;i++){
    std::fill(vis,vis+srcs+snks,false);
    matching+=dfs_match(i);
  }
  //printf("max matching: %d\n",matching);
  if(matching!=srcs){
    printf("NO\n");
    //fprintf(stderr,"not perfect\n");
    return 0;
  }
  for(int i=0;i<snks+srcs;i++){
    //printf("match %d<=>%d\n",i,match[i]);
    assert(match[match[i]]==i);
  }
  for(int i=0;i<snks;i++){
    for(int j:adj[i]){
      mini[i].push_back(match[j]);
      assert(match[match[j]]==j);
      //printf("mini: %d=>%d\n",i,match[j]);
    }
  }
  for(int i=0;i<snks;i++){
    std::fill(vis,vis+snks,false);
    dfs_mini(i);
    for(int j=0;j<snks;j++){
      if(!vis[j]){
	printf("NO\n");
	//fprintf(stderr,"not strongly connected\n");
	return 0;
      }
    }
  }
  printf("YES\n");
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cassert>

std::vector<int> dag[1000000];
int in[1000000];
int snk_id[1000000];

bool vis[1000000];

std::vector<int> adj[20];
int srcs=0,snks=0;
int match[40];

std::vector<int> mini[20];

void dfs_vis(int x){
  vis[x]=true;
  for(int y:dag[x]){
    if(!vis[y]){
      dfs_vis(y);
    }
  }
}

bool dfs_match(int x){
  if(vis[x]) return false;
  vis[x]=true;
  for(int y:adj[x]){
    if(match[y]==-1||dfs_match(match[y])){
      match[y]=x;
      match[x]=y;
      return true;
    }
  }
  return false;
}

void dfs_mini(int x){
  vis[x]=true;
  for(int y:mini[x]){
    if(!vis[y]){
      dfs_mini(y);
    }
  }
}

int main(){
  int N,M;
  scanf("%d %d",&N,&M);
  for(int i=0;i<M;i++){
    int U,V;
    scanf("%d %d",&U,&V);
    U--,V--;
    dag[U].push_back(V);
    in[V]++;
  }
  std::fill(snk_id,snk_id+N,-1);
  for(int x=0;x<N;x++){
    if(dag[x].empty()){
      snk_id[x]=snks++;
      //printf("SNK %d\n",x);
    }
  }
  for(int x=0;x<N;x++){
    if(in[x]==0){
      //printf("SRC %d\n",x);
      std::fill(vis,vis+N,false);
      dfs_vis(x);
      for(int y=0;y<N;y++){
	if(vis[y]&&snk_id[y]!=-1){
	  adj[snk_id[y]].push_back(srcs+snks);
	  adj[srcs+snks].push_back(snk_id[y]);
	  //printf("ADJ %d<=>%d\n",snk_id[y],srcs+snks);
	}
      }
      srcs++;
    }
  }
  //printf("%d,%d\n",srcs,snks);
  if(srcs!=snks){
    printf("NO\n");
    //fprintf(stderr,"srcs!=snks\n");
    return 0;
  }
  /*
  for(int i=0;i<srcs;i++){
    for(int j:adj[i]){
      printf("%d=>%d\n",i,j);
    }
  }
  */
  int matching=0;
  std::fill(match,match+srcs+snks,-1);
  for(int i=0;i<snks;i++){
    std::fill(vis,vis+srcs+snks,false);
    matching+=dfs_match(i);
  }
  //printf("max matching: %d\n",matching);
  if(matching!=srcs){
    printf("NO\n");
    //fprintf(stderr,"not perfect\n");
    return 0;
  }
  for(int i=0;i<snks+srcs;i++){
    //printf("match %d<=>%d\n",i,match[i]);
    assert(match[match[i]]==i);
  }
  for(int i=0;i<snks;i++){
    for(int j:adj[i]){
      mini[i].push_back(match[j]);
      assert(match[match[j]]==j);
      //printf("mini: %d=>%d\n",i,match[j]);
    }
  }
  for(int i=0;i<snks;i++){
    std::fill(vis,vis+snks,false);
    dfs_mini(i);
    for(int j=0;j<snks;j++){
      if(!vis[j]){
	printf("NO\n");
	//fprintf(stderr,"not strongly connected\n");
	return 0;
      }
    }
  }
  printf("YES\n");
}


// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#define pi 3.141592653589793238
#define int long long
#define ld long double
using namespace __gnu_pbds;
using namespace std;
template <typename T>
using ordered_set = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

long long power(long long a, long long b,long long mod) {
    long long res = 1;
    while (b > 0) {
        if (b & 1)
            res = res * a %mod;
        a = a * a %mod;
        b >>= 1;
    }
    return res;
}

const int szz=(1<<20);
int dp[szz+5][45];
int indeg[1000005];
int outdeg[1000005];
int vis[1000005];
vector<vector<int>> adj,adj1;
bool vis1[1000005];
int cnt[2];

int kad[szz+5];

pair<int,int> mm[1000005];
int val=0;

void dfs1(int ver)
{
    if(mm[ver].second)
        val|=(1<<(mm[ver].second-1));

    vis1[ver]=1;
    for(auto i:adj1[ver])
    {
        if(!vis1[i])
        {
            dfs1(i);
        }
    }
}

signed main()
{

ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(0);

#ifndef ONLINE_JUDGE
    if(fopen("INPUT.txt","r"))
    {
    freopen ("INPUT.txt" , "r" , stdin);
    freopen ("OUTPUT.txt" , "w" , stdout);
    }
#endif

    int n,m;
    cin>>n>>m;
    adj.resize(n+1);
    adj1.resize(n+1);
    int x,y;
    for(int i=0;i<m;i++)
    {
        cin>>x>>y;
        adj1[x].push_back(y);
        indeg[y]++;
        outdeg[x]++;
    }
    int cnt1=0,cnt2=0;
    for(int i=1;i<=n;i++)
    {
        if(indeg[i]==0)
            mm[i].first=++cnt1;
        if(outdeg[i]==0)
            mm[i].second=++cnt2;
    }

    for(int i=1;i<=n;i++)
    {
        if(mm[i].first)
        {
            val=0;
            dfs1(i);
            kad[1<<(mm[i].first-1)]=(val);
        }
    }
    int lim=(1<<cnt1);
    for(int i=0;i<lim;i++)
    {
        for(int j=0;j<cnt1;j++)
        {
            if((1<<cnt1)&i)
            {
                kad[i]|=kad[i^(1<<cnt1)];
                break;
            }
        }
    }

    for(int i=1;i<lim-1;i++)
    {
        x=__builtin_popcount(i);
        y=__builtin_popcount(kad[i]);
        if(x==y)
        {
            cout<<"NO";
            return 0;
        }
    }

    cout<<"YES";

}


// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#define pi 3.141592653589793238
#define int long long
#define ld long double
using namespace __gnu_pbds;
using namespace std;
template <typename T>
using ordered_set = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

long long power(long long a, long long b,long long mod) {
    long long res = 1;
    while (b > 0) {
        if (b & 1)
            res = res * a %mod;
        a = a * a %mod;
        b >>= 1;
    }
    return res;
}

const int szz=(1<<20);
int dp[szz+5][45];
int indeg[1000005];
int outdeg[1000005];
int vis[1000005];
vector<vector<int>> adj,adj1;
bool vis1[1000005];
int cnt[2];

void dfs(int ver)
{
    if(indeg[ver]==0)
        cnt[0]++;
    if(outdeg[ver]==0)
        cnt[1]++;

    vis[ver]=1;
    for(auto i:adj[ver])
    {
        if(!vis[i])
        {
            dfs(i);
        }
    }
}

int kad=0;
void dfs1(int ver)
{
    if(outdeg[ver]==0)
        kad++;
    vis1[ver]=1;
    for(auto i:adj1[ver])
    {
        if(!vis1[i])
        {
            dfs1(i);
        }
    }
}

signed main()
{

ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(0);

#ifndef ONLINE_JUDGE
    if(fopen("INPUT.txt","r"))
    {
    freopen ("INPUT.txt" , "r" , stdin);
    freopen ("OUTPUT.txt" , "w" , stdout);
    }
#endif

    int zz=20;
    int n,m;
    cin>>n>>m;
    adj.resize(n+1);
    adj1.resize(n+1);
    int x,y;
    for(int i=0;i<m;i++)
    {
        cin>>x>>y;
        adj[x].push_back(y);
        adj[y].push_back(x);
        adj1[x].push_back(y);
        indeg[y]++;
        outdeg[x]++;
    }

    vector<int>tot;
    bool flag=false;

    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            cnt[0]=0;
            cnt[1]=0;
            dfs(i);
            tot.push_back(cnt[0]-cnt[1]);
            if(tot.back()==0)
                flag=true;
        }
    }

    bool ok=false;
    int all=0;
    for(int i=1;i<=n;i++)
    {
        if(indeg[i]==0)
        {
            for(int j=1;j<=n;j++)
                vis1[j]=0;
            kad=0;
            all++;
            dfs1(i);
            if(kad==1)
                ok=true;
        }
    }

    if(tot.size()==1 && all==1)
    {
        cout<<"YES";
        return 0;
    }
    else if(tot.size()==1)
    {
        if(ok)
            cout<<"NO";
        else
            cout<<"YES";
        return 0;
    }

    if(flag||ok)
    {
        cout<<"NO";
        return 0;
    }
    int sz=tot.size();
    int lim=(1<<sz);
    dp[0][zz]=0;

    for(int i=0;i<lim;i++)
    {
        for(int j=0;j<=40;j++)
        {
            for(int k=0;k<sz;k++)
            {
                if(((1<<k)&i)==0)
                {
                    if(j+tot[k]>=0 && j+tot[k]<=40)
                        dp[(1<<k)|i][j+tot[k]]|=dp[i][j];
                }
            }
        }
    }
    for(int i=1;i<lim-1;i++)
    {
        if(dp[i][zz])
        {
            cout<<"NO";
            return 0;
        }
    }
    cout<<"YES";

}


// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#define pi 3.141592653589793238
#define int long long
#define ld long double
using namespace __gnu_pbds;
using namespace std;
template <typename T>
using ordered_set = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

long long power(long long a, long long b,long long mod) {
    long long res = 1;
    while (b > 0) {
        if (b & 1)
            res = res * a %mod;
        a = a * a %mod;
        b >>= 1;
    }
    return res;
}

const int szz=(1<<20);
int dp[szz+5][45];
int indeg[1000005];
int outdeg[1000005];
int vis[1000005];
vector<vector<int>> adj,adj1;
bool vis1[1000005];
int cnt[2];

void dfs(int ver)
{
    if(indeg[ver]==0)
        cnt[0]++;
    if(outdeg[ver]==0)
        cnt[1]++;

    vis[ver]=1;
    for(auto i:adj[ver])
    {
        if(!vis[i])
        {
            dfs(i);
        }
    }
}

int kad=0;
void dfs1(int ver)
{
    if(outdeg[ver]==0)
        kad++;
    vis1[ver]=1;
    for(auto i:adj1[ver])
    {
        if(!vis1[i])
        {
            dfs1(i);
        }
    }
}

signed main()
{

ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(0);

#ifndef ONLINE_JUDGE
    if(fopen("INPUT.txt","r"))
    {
    freopen ("INPUT.txt" , "r" , stdin);
    freopen ("OUTPUT.txt" , "w" , stdout);
    }
#endif

    int zz=20;
    int n,m;
    cin>>n>>m;
    adj.resize(n+1);
    adj1.resize(n+1);
    int x,y;
    for(int i=0;i<m;i++)
    {
        cin>>x>>y;
        adj[x].push_back(y);
        adj[y].push_back(x);
        adj1[x].push_back(y);
        indeg[y]++;
        outdeg[x]++;
    }

    vector<int>tot;
    bool flag=false;

    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            cnt[0]=0;
            cnt[1]=0;
            dfs(i);
            tot.push_back(cnt[0]-cnt[1]);
            if(tot.back()==0)
                flag=true;
        }
    }

    bool ok=false;
    int all=0;
    for(int i=1;i<=n;i++)
    {
        if(!indeg[i]==0)
        {
            for(int j=1;j<=n;j++)
                vis1[j]=0;
            kad=0;
            all++;
            dfs1(i);
            if(kad==1)
                ok=true;
        }
    }

    if(tot.size()==1 && all==1)
    {
        cout<<"YES";
        return 0;
    }
    else if(tot.size()==1)
    {
        if(ok)
            cout<<"NO";
        else
            cout<<"YES";
        return 0;
    }

    if(flag||ok)
    {
        cout<<"NO";
        return 0;
    }
    int sz=tot.size();
    int lim=(1<<sz);
    dp[0][zz]=0;

    for(int i=0;i<lim;i++)
    {
        for(int j=0;j<=40;j++)
        {
            for(int k=0;k<sz;k++)
            {
                if(((1<<k)&i)==0)
                {
                    if(j+tot[k]>=0 && j+tot[k]<=40)
                        dp[(1<<k)|i][j+tot[k]]|=dp[i][j];
                }
            }
        }
    }
    for(int i=1;i<lim-1;i++)
    {
        if(dp[i][zz])
        {
            cout<<"NO";
            return 0;
        }
    }
    cout<<"YES";

}


// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#define pi 3.141592653589793238
#define int long long
#define ld long double
using namespace __gnu_pbds;
using namespace std;
template <typename T>
using ordered_set = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;

long long power(long long a, long long b,long long mod) {
    long long res = 1;
    while (b > 0) {
        if (b & 1)
            res = res * a %mod;
        a = a * a %mod;
        b >>= 1;
    }
    return res;
}

const int szz=(1<<20);
int indeg[1000005];
int outdeg[1000005];
vector<vector<int>> adj1;
bool vis1[1000005];

int kad[szz+5];

pair<int,int> mm[1000005];
int val=0;

void dfs1(int ver)
{
    if(mm[ver].second)
        val|=(1<<(mm[ver].second-1));

    vis1[ver]=1;
    for(auto i:adj1[ver])
    {
        if(!vis1[i])
        {
            dfs1(i);
        }
    }
}

signed main()
{

ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(0);

#ifndef ONLINE_JUDGE
    if(fopen("INPUT.txt","r"))
    {
    freopen ("INPUT.txt" , "r" , stdin);
    freopen ("OUTPUT.txt" , "w" , stdout);
    }
#endif

    int n,m;
    cin>>n>>m;
    adj1.resize(n+1);
    int x,y;
    for(int i=0;i<m;i++)
    {
        cin>>x>>y;
        adj1[x].push_back(y);
        indeg[y]++;
        outdeg[x]++;
    }
    int cnt1=0,cnt2=0;
    for(int i=1;i<=n;i++)
    {
        if(indeg[i]==0)
            mm[i].first=++cnt1;
        if(outdeg[i]==0)
            mm[i].second=++cnt2;
    }

    for(int i=1;i<=n;i++)
    {
        if(mm[i].first)
        {
            for(int j=1;j<=n;j++)
                vis1[j]=0;
            val=0;
            dfs1(i);
            kad[1<<(mm[i].first-1)]=(val);
        }
    }

    int lim=(1<<cnt1);
    for(int i=0;i<lim;i++)
    {
        for(int j=0;j<cnt1;j++)
        {
            if((1<<j)&i)
            {
                kad[i]=(kad[i^(1<<j)]|kad[1<<j]);
            }
        }
    }

    for(int i=1;i<lim-1;i++)
    {
        x=__builtin_popcount(i);
        y=__builtin_popcount(kad[i]);
        if(x==y)
        {
            cout<<"NO";
            return 0;
        }
    }

    cout<<"YES";

}