#include <bits/stdc++.h>

using namespace std;

const int INF_32 = (1 << 30) - 1; 

template<class Abel> struct D_Graph {
	int V,E;
	Abel INF;
	vector<map<pair<int,Abel>,int>> adj;
	vector<map<pair<int,Abel>,int>> adj_inv;

	D_Graph(int V_size, Abel dist_max = INF_32) : INF(dist_max)
	{
		init(V_size);
	}

	void init(int V_size) {
		V = V_size, E = 0;
		adj.clear();
		adj_inv.clear();
		adj.resize(V + 1);
		adj_inv.resize(V + 1);
		for(int i = 1; i <= V; ++i) ++adj[0][{i,0}];
	}

	void add_edge(int from, int to, Abel cost = 1) {
		++adj[from][{to,cost}];
		++adj_inv[to][{from,cost}];
		++E;
	}

	bool erase_edge(int from, int to, Abel cost = 1) {
		bool res = 0;
		auto it = adj[from].lower_bound(make_pair(to,cost));
		if(it != end(adj[from]) && (it -> first) == make_pair(to,cost)){
			res = 1;
			if(it -> second > 1) --(it -> second);
			else adj[from].erase(it);
		}
		it = adj_inv[to].lower_bound(make_pair(from,cost));
		if(it != end(adj_inv[to]) && (it -> first) == make_pair(from,cost)){
			if(it -> second > 1) --(it -> second);
			else adj_inv[to].erase(it);
		}
		return res;
	}
	
	bool is_tied(int from, int to) {
		if(from == to) return 1;
		auto it = adj[from].lower_bound(make_pair(to,-INF));
		return it != end(adj[from]) & (it -> first).first == to;
	}
	
	bool is_leaf(int v) { return deg_out(v) == 0; }

	bool is_root(int v) { return deg_in(v) == 0; }
	
	int deg_out(int v) { return adj[v].size(); }

	int deg_in(int v) { return adj_inv[v].size(); }

	void dijkstra(vector<Abel> &dist, int src) {
		dist.clear();
		dist.assign(V + 1,INF);
		priority_queue<pair<Abel,int>,vector<pair<Abel,int>>,greater<pair<Abel,int>>> que;
		que.push({0,src});
		while(!que.empty()){
			int d = que.top().first;
			int v = que.top().second;
			que.pop();
			for(auto e : adj[v]){
				int u = e.first.first;
				int c = e.first.second;
				if(dist[u] > d + c){
					dist[v] = d + c;
					que.push({dist[v],u});
				}
			}
		}
	}

	bool is_cyclic() { vector<int> s; return !tsort(s); }

	bool tsort(vector<int> &seq, bool idx_ord = 0) {
		seq.clear();
		seq.reserve(V + 1);
		vector<int> in(V + 1);
		for(int i = 0; i <= V; ++i) in[i] = deg_in(i);
		stack<int> rt;
		rt.push(0);
		while(!rt.empty()){
			int r = rt.top();
			rt.pop();
			for(auto e : adj[r]){
				int v = e.first.first;
				if(r) --in[v];
				if(!in[v]){
					rt.push(v);
					if(idx_ord){
						auto pos = begin(seq);
						bool det = 0;
						for(auto i = begin(seq); i < end(seq); ++i){
							if(!det && v > *i) ++pos;
							else det = 1;
							if(is_tied(*i,v)){
								pos = i + 1;
								det = 0;
							}
						}
						seq.insert(pos,v);
					}else{
						seq.push_back(v);
					}
				}
			}
		}
		if(seq.size() == V) return 1;
		return 0;
	}

	void scc(vector<int> &label){
		label.assign(V + 1,0);
		stack<int> s;
		vector<int> low(V + 1);
		vector<int> idx(V + 1);
		int l = 0,c = 0;
		afx(0,c,l,s,label,low,idx);
	}

	void afx(int v, int &cnt, int &l, stack<int> &s, vector<int> &label, vector<int> &low, vector<int> &idx){
		s.push(v);
		idx[v] = low[v] = cnt++;
		for(auto e : adj[v]){
			int u = e.first.first;
			if(label[u]) continue;
			if(!idx[u]) afx(u,cnt,l,s,label,low,idx);
			low[v] = min(low[v],low[u]);
		}
		if(idx[v] == low[v]){
			++l;
			for(int t = 0; t != v; s.pop()){
				t = s.top();
				label[t] = l;
			}
		}
	}
};

int main(){
	int v,e;
	cin >> v >> e;
	D_Graph<int> G(v);
	for(int i = 0; i < e; ++i){
		int s,t;
		cin >> s >> t;
		G.add_edge(++s,++t);
	}
	cout << G.is_cyclic() << endl;
}



Measured memory_bytes: 3240