拓扑排序
把一个图的所有节点排序,使得每一条有向边$(u, v)$对应的$u$都排在$v$的前面。在图论中,这个问题称为拓扑排序(topological sort)。
不难发现:如果图中存在有向环,则不存在拓扑排序,反之则存在。所以可以用拓扑排序来检验是否存在有向环。
BFS
首先要找出所有的起点,也就是所有入度为0的点。入度为0的点在DAG中是一定存在的。(证明在这篇博客中可以找到)
若是队列不空,取出队列头$x$,遍历所有起点是$x$的边。
每次遍历中,更新数据,并删除这条边,代码实现就是这条边的终点$y$的入度减一。
如果$y$的入度被减为0,则说明$y$的所有前驱都被计算过了,$y$成了新的起点,将$y$插入队列。
如此循环直至队列空。
最后统计数据。
如果要判定有向环,要加一个vis[], 确保每个点只访问一次。
1 | //这里我用邻接表储存边 |
DFS
《算法竞赛入门经典》里还给出了一种DFS的拓扑排序,这里只是输出一张图的拓扑排序。
1 | int c[maxn]; |
这里用到了一个 c 数组,c[u]=0 表示从来没有访问过(从来没有调用过dfs(u));c[u]=1 表示已经访问过,并且还递归访问过它所有的子孙(即dfs(u)曾被调用过,并已经返回);c[u]=-1 表示正在访问(即递归调用dfs(u)正在栈帧中,尚未返回)。
参考
https://www.luogu.com.cn/blog/106510/topo-sort
《算法竞赛入门经典》