拓扑排序tupo模版
一个n年前学的东西,发现还没写博客,就来上一篇
定义:
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
一句话概括性质:在一个DAG中,每一个能到达点v的点,在线性序列中都出现在v之前。
那么从这个性质就能看出拓扑排序的用处了:用来得到处理问题的顺序
代码实现
方法1:BFS(SPFA优化)
1、先寻找入度为0的点,把它加入队列。
2、搜寻队列,把队列的点G删去,则如果有点的入度有G点的话,入度- -,当发现又出现入度为0的点时,将该点加入队列。
3、拓扑排序的结果为该队列,在执行删点操作的时候存储在一个数组及可。
tips1:如果不一定是DAG,那么就要判是否有环。
Topo(G){
统计图G中每个点的入度(可计算重边,但不可计算自环),记为degree[i]
初始化queue和result为空的队列,并将所有degree为0的点加入queue(用result或者一个数组存储拓扑排序后生成的线性序列)
while (!queue.empty()){
u = queue.pop() // 队首
result.push(u)
for e 是u的出边(若上面计算了重边,这里也要算,与上面一致)
v是e的指向的点
degree[v]--
if (degree[v] == 0) queue.push(v)
}
return result
}
方法2:记忆化搜索(反正我是一般不用)
calculate(u){
if (u 已经搜索过) return table[u]
ans = -inf
for (v 是u的出边指向的点)
ans = max(ans, value[u] + calculate(v))
标记u已经搜索过
table[u] = ans
return ans
}
for (i 是G的所有节点)
result = max(result, calculate(i))
print(result)