#include <bits/stdc++.h>

// Just stands for connections
class LinkList
{
public:
    LinkList(const std::size_t v) : m_v{v}
    {
        m_table.resize(v);
        m_reversed_table.resize(v);
    }
    void addEdge(const std::size_t from, const std::size_t to)
    {
        m_e++;
        m_table[from].push_back(to);
        m_reversed_table[to].push_back(from);
    }

    void TopologocalSort(std::vector<std::size_t>& srt) const
    {
        srt.clear();
        std::vector<bool> used(m_v, false);
        for (std::size_t i = 0; i < m_v; i++) {
            dfs_topo(i, used, srt);
        }
        std::reverse(srt.begin(), srt.end());
    }

    std::size_t SCC(std::vector<std::size_t>& cmp) const
    {
        assert(cmp.size() == m_v);
        for (std::size_t i = 0; i < m_v; i++) {
            cmp[i] = 0;
        }

        std::vector<std::size_t> st;
        std::vector<bool> used(m_v, false);
        for (std::size_t i = 0; i < m_v; i++) {
            if (not used[i]) {
                dfs1_scc(i, st, used);
            }
        }

        for (std::size_t i = 0; i < m_v; i++) {
            used[i] = false;
        }
        std::size_t comp = 0;
        for (std::size_t i = 0; i < st.size(); i++) {
            const std::size_t s = st[st.size() - i - 1];
            if (not used[s]) {
                dfs2_scc(s, comp++, cmp, used);
            }
        }
        return comp;
    }

    std::size_t getV() const
    {
        return m_v;
    }

    std::size_t getE() const
    {
        return m_e;
    }

    const std::vector<std::vector<std::size_t>>& getEdge() const
    {
        return m_table;
    }

    std::vector<std::vector<std::size_t>>& getEdge()
    {
        return m_table;
    }

    const std::vector<std::vector<std::size_t>>& getReversedEdge() const
    {
        return m_reversed_table;
    }

    std::vector<std::vector<std::size_t>>& getReversedEdge()
    {
        return m_reversed_table;
    }

    void printDot() const
    {
        std::cout << "digraph \"Graph\" {\n";

        std::cout << "  graph [\n"
                  << "    charset = \"UTF-8\";\n"
                  << "    label = \"Graph\",\n"
                  << "    labelloc = \"t\",\n"
                  << "    labeljust = \"c\",\n"
                  << "    bgcolor = \"#343434\",\n"
                  << "    fontcolor = white,\n"
                  << "    fontsize = 18,\n"
                  << "    style = \"filled\",\n"
                  << "    rankdir = TB,\n"
                  << "    margin = 0.2,\n"
                  << "    splines = spline,\n"
                  << "    ranksep = 1.0,\n"
                  << "    nodesep = 0.9,\n"
                  << "    layout = dot\n"
                  << "  ];\n\n";

        std::cout << "  node [\n"
                  << "    colorscheme = \"rdylgn11\"\n"
                  << "    style = \"solid,filled\",\n"
                  << "    fontsize = 16,\n"
                  << "    fontcolor = 6,\n"
                  << "    fontname = \"Migu 1M\",\n"
                  << "    color = 7,\n"
                  << "    fillcolor = 11,\n"
                  << "    fixedsize = true,\n"
                  << "    height = 0.6,\n"
                  << "    width = 1.2\n"
                  << "  ];\n\n";

        std::cout << "  edge [\n"
                  << "    style = solid,\n"
                  << "    fontsize = 14,\n"
                  << "    fontcolor = white,\n"
                  << "    fontname = \"Migu 1M\",\n"
                  << "    color = white,\n"
                  << "    labelfloat = true,\n"
                  << "    labeldistance = 2.5,\n"
                  << "    labelangle = 70\n"
                  << "  ];\n\n";

        std::cout << "  // Node definition\n";
        for (std::size_t i = 0; i < m_v; i++) {
            std::cout << "  " << i << ";\n";
        }
        std::cout << "\n";
        std::cout << "  // Edge definition\n";
        for (std::size_t i = 0; i < m_v; i++) {
            for (const std::size_t to : m_table[i]) {
                std::cout << "  " << i << " -> " << to << ";\n";
            }
        }
        std::cout << "}" << std::endl;
    }


private:
    void dfs_topo(const std::size_t s, std::vector<bool>& used, std::vector<std::size_t>& srt) const
    {
        assert(s < m_v);
        assert(used.size() == m_v);
        if (not used[s]) {
            used[s] = true;
            for (const std::size_t to : m_table[s]) {
                dfs_topo(to, used, srt);
            }
            srt.push_back(s);
        }
    }

    void dfs1_scc(const std::size_t s, std::vector<std::size_t>& st, std::vector<bool>& used) const
    {
        assert(s < m_v);
        assert(used.size() == m_v);
        used[s] = true;
        for (const std::size_t to : m_table[s]) {
            if (not used[to]) {
                dfs1_scc(to, st, used);
            }
        }
        st.push_back(s);
    }

    void dfs2_scc(const std::size_t s, const std::size_t index, std::vector<std::size_t>& cmp, std::vector<bool>& used) const
    {
        assert(s < m_v);
        assert(index < m_v);
        assert(cmp.size() == m_v);
        cmp[s] = index;
        used[s] = true;
        for (const std::size_t to : m_reversed_table[s]) {
            if (not used[to]) {
                dfs2_scc(to, index, cmp, used);
            }
        }
    };

    const std::size_t m_v;
    std::size_t m_e;
    std::vector<std::vector<std::size_t>> m_table;
    std::vector<std::vector<std::size_t>> m_reversed_table;
};


int main()
{
    std::size_t V, E;
    std::cin >> V >> E;
    LinkList g{V};
    for (std::size_t i = 0; i < E; i++) {
        std::size_t s, t;
        std::cin >> s >> t;
        g.addEdge(s, t);
    }

    std::vector<std::size_t> srt;
    g.TopologocalSort(srt);
    for (std::size_t i = 0; i < V; i++) {
        std::cout << srt[i] << std::endl;
    }

    return 0;
}

Measured memory_bytes: 4752