算法专题——拓扑排序
作者:互联网
拓扑序的概念
将节点的编号按照序列的形式排开,则我们将前面节点总是指向后面节点,后面节点不会指向前面节点的序列称为拓扑序列。并将可以得到拓扑序列的图称为拓扑图。如上图,就是一个拓扑图,可以得到拓扑序,123
。
拓扑图的几个性质
- 拓扑图总是有向无环图。有环图得不到拓扑序。有向无环图总是可以得到入度为0的节点,. 依据这一点可以得到拓扑序
- 拓扑图可以看为由若干指向相同的链表黏连而成的, 拓扑图中入度为0的点为链表的起点, 出度为0的点为链表的终点.
求拓扑序
借助拓扑序总是可以找到入度为0的点的性质, 我们只要总是将入度为0的点弹出即可得到拓扑序, 于是我们可以通过BFS实现, 见伪代码
for (所有点)
if (入度为0) 入队que
while(que非空) {
得到对头u
for (与u相连的点) {
与u相连的点的入度--;
if (如果该点入度减为为0) 入队que
}
}
拓扑序的特点
拓扑图可以看为由若干指向相同的链表黏连而成的, 因此具有非常好的性质, 以及特点.
拓扑序对于处理dp具有天然的优势, 所以可以按照拓扑序的方法对拓扑图进行dp递推, 进而也可以处理最短/长路问题, 时间复杂度可以减到线性.
拓扑图固定的知识点不多, 但有一些零零碎碎的二级结论不少, 可能会作为题目的一环让选手手推结论. 具体的可以看例题.
例题
三道题与强连通分量结合的题, 见博客算法专题——强连通分量.
可达性统计
题面:
分析:
基本可以转移到dp的做法, 每一个节点记录可以访问到的节点分别是什么, 转移的时候进行处理.
可以用bitset存储所含的节点, 也刚好不会超时, 结合拓扑dp即可接出来. 见下面核心代码.
车站分级
题面:
分析:
可以发现停靠站和非停靠站之间具有某些特殊的关系, 即非停靠站的等级大小一定都小于停靠站的等级大小. 于是问题就变得和差分约束差不多了, 但是如果用传统的建图方式会有些问题, 可以发现非停靠站的每一个站点的等级由于小于停靠站每一个站点的等级, 所以总共需要连接非停靠站站点数量 * 停靠站站点数量
条边, 最坏的情况下, 需要连接车次 * 停靠站 * 非停靠站 == 1000 * 500 * 500 == 2.5 * 10 ^ 8
条边, 时空复杂度都会爆掉. (下为一个车次需要建的边, 没有画出边的方向, 实际上是有的, 方向均为非停靠站指向停靠站)
所以需要改变一下建图的方法, 可以引入一个虚拟原点, 见下图, 可以设置非停靠站指向虚拟原点的边的边权为0, 虚拟原点指向停靠站的边的边权为1, 这样建出的图的效果与上面是一样的, 但是需要的空间却少了很多, 变成了非停靠站站点数量 + 停靠站站点数量
条边.
剩下的就是普通的差分约束了, 核心代码见下.
标签:拓扑图,停靠站,拓扑,入度,算法,可以,排序,节点 来源: https://www.cnblogs.com/TanJI-life/p/15382571.html