拓扑排序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)

给几道例题

洛谷P1347 排序
洛谷P1983 [NOIP2013 普及组] 车站分级

posted @ 2021-09-03 17:52  Mint-hexagram  阅读(92)  评论(0编辑  收藏  举报