Problem: <image>


A directed acyclic graph (DAG) can be used to represent the ordering of tasks. Tasks are represented by vertices and constraints where one task can begin before another, are represented by edges. For example, in the above example, you can undertake task B after both task A and task B are finished. You can obtain the proper sequence of all the tasks by a topological sort.

Given a DAG $G$, print the order of vertices after the topological sort.

Constraints

* $1 \leq |V| \leq 10,000$
* $0 \leq |E| \leq 100,000$
* There are no parallel edges in $G$
* There are no self loops in $G$

Input

A directed graph $G$ is given in the following format:
$|V|\;|E|$
$s_0 \; t_0$
$s_1 \; t_1$
:
$s_{|E|-1} \; t_{|E|-1}$



$|V|$ is the number of vertices and $|E|$ is the number of edges in the graph. The graph vertices are named with the numbers $0, 1,..., |V|-1$ respectively.

$s_i$ and $t_i$ represent source and target nodes of $i$-th edge (directed).

Output

Print the vertices numbers in order. Print a number in a line.

If there are multiple possible solutions, print any one of them (the solution is judged by a special validator).

Example

Input

6 6
0 1
1 2
3 1
3 4
4 5
5 2


Output

0
3
1
4
5
2

Solution (in JAVA):

Solution:
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {

    public static void main(String[] args) {
        FastScanner sc = new FastScanner();
         
        int v = sc.nextInt();
        int e = sc.nextInt();
        DGraph g = new DGraph(v);
        
        for(int i=0;i<e;i++){
        	g.addEdge(sc.nextInt(), sc.nextInt());
        }
        
        for(int i:g.topologicalSort()){
        	System.out.println(i);
        }
    }
	
}

class DGraph {

	NodeList[] nlist; //隣接リスト
	
	public DGraph(int vnum){
		this.nlist = new NodeList[vnum];
		for(int i=0;i<vnum;i++){
			nlist[i] = new NodeList();
		}
	}
	
	//辺の追加（同じ辺を複数回追加すると多重辺になる）
	void addEdge(int n, int m){
		nlist[n].add(m);
	}
	
	//頂点数を返す
	int vnum(){
		return nlist.length;
	}
	
	//辺数を返す
	int edgeNum(){
		int sum = 0;
		for(NodeList l:nlist){
			sum += l.size();
		}
		return sum;
	}
	
	//到達判定
	boolean isNext(int n, int m){
		return nlist[n].contains(m);
	}
	
	//1歩で到達可能な全ての頂点を返す
	NodeList nextList(int n){
		return nlist[n];
	}

	//トポロジカルソート（ans.size()!=vnum()ならDAGでなく、出力に意味はない））
	ArrayList<Integer> topologicalSort(){
		int idig[] = new int[vnum()]; //入次数
		for(int i=0;i<vnum();i++){
			for(int j:nextList(i)){
				idig[j] ++;
			}
		}
		ArrayDeque<Integer> q = new ArrayDeque<>();
		
		for(int i=0;i<vnum();i++){
			if(idig[i]==0){
				q.add(i); //入次数が0ならキューに入れる（DAGなら必ず存在）
			}
		}
		
		ArrayList<Integer> ans = new ArrayList<>();
		
		while(!q.isEmpty()){
			int now = q.pollFirst();
			ans.add(now);
			
			for(int j:nextList(now)){
				idig[j] --;
				if(idig[j]==0){
					q.add(j);
				}
			}
		}
		
		return ans;
	}
	
	//サイクルを持つか（DAGか）
	boolean hasCycle(){
		return !(topologicalSort().size() == vnum());
	}
	
	class NodeList extends ArrayList<Integer>{
		private static final long serialVersionUID = -4461479015945373120L;
	}
}

class FastScanner {
	private final InputStream in = System.in;
	private final byte[] buffer = new byte[1024];
	private int ptr = 0;
	private int buflen = 0;
	private boolean hasNextByte() {
		if (ptr < buflen) {
			return true;
		} else {
			ptr = 0;
			try {
				buflen = in.read(buffer);
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (buflen <= 0) {
				return false;
			}
		}
		return true;
	}
	private int readByte() {
		if (hasNextByte())
			return buffer[ptr++];
		else
			return -1;
	}
	private static boolean isPrintableChar(int c) {
		return 33 <= c && c <= 126;
	}
	public boolean hasNext() {
		while (hasNextByte() && !isPrintableChar(buffer[ptr]))
			ptr++;
		return hasNextByte();
	}
	public String next() {
		if (!hasNext())
			throw new NoSuchElementException();
		StringBuilder sb = new StringBuilder();
		int b = readByte();
		while (isPrintableChar(b)) {
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}
	public long nextLong() {
		if (!hasNext())
			throw new NoSuchElementException();
		long n = 0;
		boolean minus = false;
		int b = readByte();
		if (b == '-') {
			minus = true;
			b = readByte();
		}
		if (b < '0' || '9' < b) {
			throw new NumberFormatException();
		}
		while (true) {
			if ('0' <= b && b <= '9') {
				n *= 10;
				n += b - '0';
			} else if (b == -1 || !isPrintableChar(b)) {
				return minus ? -n : n;
			} else {
				throw new NumberFormatException();
			}
			b = readByte();
		}
	}
	public int nextInt() {
		long nl = nextLong();
		if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE)
			throw new NumberFormatException();
		return (int) nl;
	}
	public double nextDouble() {
		return Double.parseDouble(next());
	}
}