// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_4_A&lang=jp
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, j) for(int i = 0; i < (int)(j); i++)
constexpr int INF = 1 << 28;
using EdgeList = vector<vector<int>>;
// ?????£?????????????????°?????? E ????????£????????????????§£(Tarjan's algorithm)
// O(N + M) N: ????????°, M: ?????°
vector<vector<int>> strongly_connected_components_tarjan(const EdgeList &E) {
    int N = E.size();
    vector<int> ord(N, -1), low(N);
    int cnt = 0;
    stack<int> stk;
    vector<bool> on_stack(N);
    vector<vector<int>> scc;    
    function<void(int, int)> dfs = [&] (int now, int pre) {
        stk.push(now);
        on_stack[now] = true;
        ord[now] = cnt++;
        low[now] = ord[now];
        for(int nxt : E[now]) {
            if(ord[nxt] < 0) {
                // not visited
                dfs(nxt, now);
                low[now] = min(low[now], low[nxt]);
            } else if(on_stack[nxt]) {
                // visited
                low[now] = min(low[now], ord[nxt]);
            } 
        }
        if(ord[now] == low[now]) {
            scc.push_back({});
            while(true) {
                int v = stk.top(); stk.pop();
                scc.back().push_back(v);
                on_stack[v] = false;
                if(v == now) break;
            }
        }
    };
    // ??£?????°????????????dfs(0)????????§OK
    rep(i, N) if(ord[i] < 0) dfs(i, -1);
    return scc;
}
// ????????°?????????????????????????????????????????????
bool detect_cycle_tarjan(const EdgeList &E) {
    auto scc = strongly_connected_components_tarjan(E);
    bool res = false;
    for(auto &g : scc) res |= g.size() > 1;
    return res;
}
// ????????°?????? E ????????£????????????????§£(?????¬)
// O(N + M) N: ????????°, M: ?????°
// -> ??????????????????????????????????????????????????????????????£????????????0 ??? root
vector<int> strongly_connected_components_ant(const EdgeList &E) {
    int N = E.size();
    EdgeList rE(N); rep(i, N) for(int nxt : E[i]) rE[nxt].push_back(i); // ??????    
    vector<char> used(N);
    vector<int> vs; // DFS??°????????????
    vector<int> topological_no(N);
    function<void(int)> dfs = [&] (int v) {
        used[v] = true;
        for(int nxt : E[v]) if(not used[nxt]) dfs(nxt);
        vs.push_back(v);
    };
    function<void(int, int)> rdfs = [&] (int v, int k) {
        topological_no[v] = k;
        used[v] = true;
        for(int nxt : rE[v]) if(not used[nxt]) rdfs(nxt, k);
    };
    rep(v, N) if(not used[v]) dfs(v);
    fill(begin(used), end(used), false);
    int k = 0;
    for(int i = vs.size() - 1; i >= 0; i--) if(not used[vs[i]]) rdfs(vs[i], k++);
    return topological_no;
}
// ????????°?????????????????????????????????????????????
bool detect_cycle_ant(const EdgeList &E) {
    auto scc = strongly_connected_components_ant(E);
    set<int> found;
    for(int v : scc) {
        if(found.count(v)) return true;
        found.insert(v);
    }
    return false;
}
int main() {
    int N, M; cin >> N >> M;
    EdgeList E(N);
    rep(i, M) {
        int a, b; cin >> a >> b;
        E[a].push_back(b);
    }
    auto scc1 = strongly_connected_components_tarjan(E);
    reverse(begin(scc1), end(scc1));
    vector<int> ans1;
    {
        for(vector<int> g : scc1) {
            sort(begin(g), end(g));
            for(int a : g) ans1.push_back(a);
        }
    }
    auto scc2 = strongly_connected_components_ant(E);
    vector<int> ans2(N);
    {
        vector<pair<int, int>> P(N);
        rep(i, N) P[i] = make_pair(scc2[i], i);
        sort(begin(P), end(P));
        rep(i, N) ans2[i] = P[i].second;
    }
    assert(ans1 == ans2);
    for(int a : ans1) cout << a << endl;
    return 0;
}

Measured memory_bytes: 4828