图论
笔者开始复习图论了!于是就有了这篇 blog。
最短路
- 单源最短路
单源最短路径问题,即求解从起点
Dijkstra 利用贪心思想,每次取出未被标记、距离最小的点然后松弛该点的所有出边。在稠密图上,我们直接使用
由于 Dijkstra 的贪心性质,该算法只适用于边全均非负的情况。同时,在负权图上,我们可以利用特殊构造方式,让节点不断被重新松弛,从而让 Dijkstra 的时间复杂度退化到指数级别。
Bellman-Ford 基于迭代思想,通过扫描所有边,不断对节点进行松弛,让所有边都满足三角形不等式,时间复杂度
SPFA 算法通过队列对 Bellman-Ford 进行优化,把待扩展的节点保存在队列内,避免了对无用节点的扫描,在随机图上复杂度为
值得一提,在负权图上这两种算法也能正常运作。
另外,在图上进行动态规划时,可能会遇到环形依赖,即图不是一张 DAG。通常情况下有两个解决办法:
· 利用 Dijkstra 的贪心思想,即状态之间转移时,代价都是正的,所以能把目前队列中的最小代价的状态确定为一个最优状态。换句话说,Dijkstra 是在“有单调性的图上”,利用单调性可以确定出一个拓扑序,按照这个序列进行转移就能得到正确答案。
· 借助 SPFA 算法进行动态规划,即在这张图上多次迭代,最后把答案收敛出来。
习题:
P1875 佳佳的魔法药水 最短路扩展 + 最短路计数
P4042 [AHOI2014/JSOI2014] 骑士游戏 最短路扩展
P1462 通往奥格瑞玛的道路 二分答案最短路
- 最短路树
最短路树是原图的一棵生成树,通常以起点
对于任意点
建图:求解最短路的过程中,保留最后一次松弛点
- 最短路DAG
对于任意节点
最短路 DAG 是有向无环图。若存在环,则说明原图中存在负环或
最短路 DAG 的每一棵生成树都是最短路树,所有最短路树都是最短路 DAG 的生成树。
建图:求出最短路后, 遍历所有边
- 单源次短路
对于非严格次短路,图中存在一条以上最短路时,非严格次短路就是最短路;否则非严格次短路就是严格次短路。
类似用 dijkstra 算法求解最短路的过程,我们可以用两个数组
如果图中不存在非正环,那么任意一条次短路至多经过一个点两次。
所以我们同样可以用
另外一种做法是,在原图和反图上求解单源最短路,得到每个节点到起点
由于严格次短路至少有一条边与最短路不同,我们可以枚举不在最短路上的边
习题:
P2865 [USACO06NOV] Roadblocks G
P2829 大逃离
- 分层图最短路
当我们需要额外的信息来维护最短路的时候,我们可以考虑使用分层图最短路。
中心思想:建立多层图,同层之间正常连接,不同层之间用优惠边权连接,然后求解最短路。
众所周知,动态规划对状态空间的遍历构成一张有向无环图,这说明分层图问题从 DP 角度看其实是二维 DP 问题。
习题:
P4822 [BJWC2012] 冻结
P1266 速度限制
P4568 飞行路线
P1948 Telephone Lines S
P3119 [USACO15JAN] Grass Cownoisseur G 缩点 + 分层图
- 负环
利用 Bellman-Ford 或者 SPFA 算法,我们可以在
- 差分约束
差分约束系统指若干个形如
对于若干二元关系约束,我们可以把这些条件转化为图上问题,最常见即在两者间连边。
把每个变量
- 全源最短路径
全源最短路即图中任意两点间的最短路径,求解全源最短路,我们通常使用 Floyd 算法。
Floyd 的本质是动态规划,设
注意这里
类似背包问题的状态转移方程,我们可以压掉
- 传递闭包
传递闭包,指通过具有传递性的二元关系,推导出尽量多的元素的关系的问题。
使用 Floyd 算法可以解决传递闭包问题。
- 无向图最小环
考虑 Floyd 算法的过程,当外层循环
那么,
我们对于所有的
- 有向图最小环
对于有向图的最小环问题,我们可以枚举起点
Tarjan算法
Tarjan 算法可以在线性时间内快速求解无向图和有向图的连通性问题。