#include <bits/stdc++.h> 

using namespace std;

#define rep(i,n) for(int (i) = 0; (i) < (n); ++(i))

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

template<class Abel> struct D_Graph {
	int V,E;
	Abel INF;
	vector<vector<pair<int,Abel>>> adj;
	vector<vector<pair<int,Abel>>> adj_inv;
	
	D_Graph(int V_size = 0, 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);
		adj[0].resize(V);
		for(int i = 1; i <= V; ++i){
			adj[0][i - 1] = {i,0};
			adj[i].reserve(min(V,100));
			adj_inv[i].reserve(min(V,100));
		}
	}
	
	int deg_out(int v) { return adj[v].size(); }
	
	int deg_in(int v) { return adj_inv[v].size(); }
	
	bool is_leaf(int v) { return deg_out(v) == 0; }
	
	bool is_root(int v) { return deg_in(v) == 0; }
	
	void add_edge(int from, int to, Abel cost = 1) {
		adj[from].push_back({to,cost});
		adj_inv[to].push_back({from,cost});
		++E;
	}
	
	void sort_adj() {
		for(int i = 0; i <= V; ++i) sort_adj(i);
	}
	
	void sort_adj(int v) {
		sort(begin(adj[v]),end(adj[v]));
		sort(begin(adj_inv[v]),end(adj_inv[v]));
	}
	
	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();
			if(dist[v] <= d) continue;
			dist[v] = d;
			for(auto e : adj[v]) que.push({e.second + d,e.first});
		}
	}
	
	bool is_cyclic() {
		vector<int> s;
		return !tsort(s);
	}
	
	bool tsort(vector<int> &seq, bool idx_ord = 0) {
		seq.clear();
		seq.reserve(V + 1);
		sort_adj();
		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;
				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; 
							auto u = lower_bound(begin(adj[*i]),end(adj[*i]),make_pair(v,-INF));
							if(u < end(adj[*i]) && u->first == 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,0);
		int l = 0,c = 0;
		dfs(0,c,l,s,label,low,idx);
	}
	
	void dfs(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;
			if(label[u]) continue;
			if(!idx[u]) dfs(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(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	
	int V,E,s,t; cin>>V>>E;
	D_Graph<int> G(V);
	rep(i,E){
		cin>>s>>t;
		G.add_edge(++s,++t);
	}
	vector<int> v;
	G.tsort(v);
	for(int e : v) cout<<e - 1<<endl;
}





Measured memory_bytes: 19532