参考:https://zhuanlan.zhihu.com/p/260112913

    拓扑排序是对DAG(有向无环图)上的节点进行排序,使得对于每一条有向边 拓扑排序 - 图1拓扑排序 - 图2 都在 拓扑排序 - 图3 之前出现。简单地说,是在不破坏节点先后顺序的前提下,把DAG拉成一条。如果以游戏中的科技树(虽然名字带树,其实常常不是树而只是DAG)举例,拓扑排序就是找到一种可能的点科技树的顺序

    Kahn算法
    一句话:一直拿走入度为0的点。
    O(N+M) n,m分别为点数和边数

    1. // deg是入度,在存图的时候需要录入数据
    2. // A是排序后的数组
    3. int deg[MAXN], A[MAXN];
    4. bool toposort(int n)
    5. {
    6. int cnt = 0;
    7. queue<int> q;
    8. for (int i = 1; i <= n; ++i)
    9. if (deg[i] == 0)
    10. q.push(i);
    11. while (!q.empty())
    12. {
    13. int t = q.front();
    14. q.pop();
    15. A[cnt++] = t;
    16. for (auto to : edges[t])
    17. {
    18. deg[to]--;
    19. if (deg[to] == 0) // 出现了新的入度为0的点
    20. q.push(to);
    21. }
    22. }
    23. return cnt == n;
    24. }

    返回值为是否成功进行拓扑排序,也即是否存在环。也就是说拓扑排序是可以用来简单地判环的。有时会要求输出字典序最小的方案,这时把queue改成priority_queue即可,复杂度会多一个log