using System;
using System.Collections.Generic;
using System.Linq;

namespace Competitive
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            int[] values = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
            int N = values[0];
            int E = values[1];

            var G = new Graph<int>();
            for (int i = 0; i < N; i++) G.AddNode(i);
            for (int i = 0; i < E; i++)
            {
                int[] _edges = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
                G.AddEdge(_edges[0], _edges[1]);
            }

            var ret = G.TopologicalSort();
            for (int i = 0; i < ret.Count; i++)
            {
                Console.WriteLine(ret[i]);
            }

        }
    }

    // 有向グラフ
    internal class Graph<T>
    {
        private List<Node> nodes;
        private List<Edge> edges;
        private Dictionary<T, Node> dic;

        private Node this[int index]
        {
            get { return nodes[index]; }
        }

        internal class Node
        {
            public int No;
            public T Obj;
            public List<Edge> Edges;

            public Node(int no, T obj)
            {
                No = no;
                Obj = obj;
                Edges = new List<Edge>();
            }
        }

        internal class Edge
        {
            public int From;
            public int To;
        }

        public Graph()
        {
            nodes = new List<Node>();
            edges = new List<Edge>();
            dic = new Dictionary<T, Node>();
        }

        public List<T> Nodes()
        {
            return nodes.Select(n => n.Obj).ToList();
        }

        public List<T> Successors(T obj)
        {
            var node = dic[obj];
            return node.Edges.Select(e => this[e.To].Obj).Distinct().ToList();
        }

        public void AddNode(T obj)
        {
            // TODO: 重複処理
            if (dic.ContainsKey(obj))
            {
                throw new Exception("既にノードに存在します");
            }

            int no = nodes.Count;
            var node = new Node(no, obj);
            dic.Add(obj, node);
            nodes.Add(node);
        }

        public void AddEdge(T fm, T to)
        {
            if (!dic.ContainsKey(fm) || !dic.ContainsKey(to)) throw new Exception("ノードが存在しません");
            var fmIdx = dic[fm].No;
            var toIdx = dic[to].No;
            var edge = new Edge {From = fmIdx, To = toIdx};
            edges.Add(edge);
            this[fmIdx].Edges.Add(edge);
        }

        public List<List<T>> Condensation()
        {
            throw new NotImplementedException();
        }

        public List<T> TopologicalSort()
        {
            // DFSを行う
            // TODO: 辞書式トポロジカルソートの方が安定するか？
            // 閉路が存在した場合、nullを返す
            // 閉路が存在しない場合、探索済のノードから順にセットしていく。それを反転したものを返り値とする。
            // http://www.prefield.com/algorithm/graph/topological_sort.html

            int n = nodes.Count;
            var color = Util.EmptyList<int>(n);
            var order = new List<int>();

            for (int i = 0; i < n; i++)
                if (color[i] == 0)
                {
                    bool visitSuccess = Visit(i, color, order);
                    if (!visitSuccess) return null;
                }

            order.Reverse();
            return order.Select(i => this[i].Obj).ToList();

        }

        bool Visit(int i, List<int> color, List<int> order)
        {
            color[i] = 1; // 探索中
            var node = this[i];
            foreach (var e in node.Edges)
            {
                if (color[e.To] == 2) continue; // 探索済
                if (color[e.To] == 1) return false; // 探索中Nodeに到達してしまった
                bool visitSuccess = Visit(e.To, color, order);
                if (!visitSuccess) return false;
            }

            order.Add(i);
            color[i] = 2; // 探索済
            return true;
        }

      
    }
    
    internal static class Util
    {
        public static List<T> EmptyList<T>(int count)
        {
            return Enumerable.Range(0, count).Select(i => default(T)).ToList();
        }
    }

}


Measured memory_bytes: 15716