Skip to content

最短路相关

floyd

适用范围

稠密图全源最短路。

算法原理

常见的 floyd 是实时维护一个点集 $V$,当前 $dis[i][j]$ 表示从 $i$ 到 $j$ 只能中途经过 $V$ 中点的最短路。注意,这里的“中途”不含起点和终点(这是因为 朴素的 floyd 初始 $f[i][j]$ 表示邻接矩阵)。当然,可以改成每次路径全程不经过某些点,这只需要特判起点和终点即可。

正确性证明

每次新增一个点,$i,j$ 之间的最短路要么经过,要么不经过。

  • 不经过就是原来的 $dis$。
  • 经过的话,如果图没有负环,必然经过恰一次,就是 $dis[i][k]+dis[k][j]$。 注意这里是滚动实现,因为没有负环时,经过同一个点两次必然不优。

判负环

必然有一个点经过了两次,做两次 floyd,在第二次看能不能再松弛即可。

扩展

结合线段树分治实现稠密图加点删点全源最短路(边的问题类似)。

dijkstra

适用范围

非负权单源最短路。

原理

简单贪心,略。

扩展:模拟 dij

dij 的过程非常简单,核心就两步:

  • 找到最小点。
  • 用当前点松弛所有相连点。

模拟的难点在于松弛部分,通常可以用 DS 实现。经典的:处理区间连边。

bellman - ford

正确性证明

没有负环的时候,最短路长度 $\leq n$。

spfa

复杂度证明

每个点入队必然因为某条新边导致的最短路,最多入队 $m$ 次。

判负环

建立超级源点,连向每一个点,跑 spfa(保证连通性),同时记录最短路点数,超过 $n$ 就有负环。

优化

  • 直接优化(正式比赛不要往这方面想):比较常用的是 SLF 优化。
  • 去掉负权边跑 dij(常用):
    • 重新设计建图。
    • 结合图的特性,合理赋势能。

k - bfs

适用范围

边权非负且值域可以接受。

本质

模拟 dij,通过让每个队列内部不降,保证取到最小值。

复杂度

$O(nv + m)$,特别的有 01bfs。

差分约束问题

  • 处理不等关系:直接建边。
  • 相等关系:建双向边。
  • 和特殊值的不等关系:取虚点建边。

johnson

利用差分约束实现一般图的赋势能。

最短路树

以下都是有向任意边权图。

定义

  • 最短路 DAG:满足 $dis[v]=dis[u]+w(u,v)$ 的边组成的图。
  • 最短路树:最短路 DAG 的生成树,注意,这是有向树。

性质

  • (核心)非树边满足三角形不等式。
  • 任何一条从 $st$ 出发到 $ed$ 的简单路径和合法的非树边序列一一对应。合法:序列中的任何非树边前驱能只走树边到该非树边。
  • 路径权值和非树边序列权值的对应关系:
    • 将非树边的权值重定义为 $dis[v]+w(u,v)-dis[u]$。
    • 路径的长度就是非树边权值和加上 $st,ed$ 之间的最短路长度。

k 短路

  • 不要求简单路径:在 dij 过程中第 $k$ 次取出的 $x$ 点 $dis$ 就是 $k$ 短路。
  • 简单路径:结合最短路树和调整法实现。

同余最短路

适用范围

存在性完全背包问题。

原理

任取一个基准物品,记其体积为 $mod$。那么,对于 $0\leq i\lt mod$,$dis[i]$ 表示到达 $j\times mod + i$ 的最小的 $j\times mod + i$。对于体积为 $v$ 的物品,其松弛形如 $chkmi(dis[(i + v)%mod],dis[i]+v)$。判定一个体积 $v$ 是否可以表示出来,可以直接看 $dis[v%mod]$ 和 $v$ 的大小关系。

优化思考

直接实现是最短路,但是,这是否可以直接 DP 去掉 $\log$ 呢?观察松弛进行的条件,假设从 $st$ 开始,持续松弛成功,过程形如环上跳。而这个跳肯定不会一直成功到 $st$(因为一开始就是用 $dis[st]$ 松弛的)。所以,可以枚举 $st$,模拟跳的过程,转两圈,保证每个环上点都松弛到位。核心:不会经过同一个状态。

删边最短路

处理 无向正权图 的删边后的固定起终点最短路。下面求 1 到 $n$ 的删边最短路,建出两个最短路树做,懒得写了,太少用了。

次短路的扩展应用:维护多个最值处理限制

适用背景

处理带限制的最短路(DP 转移)。限制可以被刻画成:解的特征值恰不等于给定集合中的任何一个,其中,特征值需要自己设计。

适用条件

对于同一个点(状态),不合法的边(转移)的数量是可以接受的。

经典例子

  • 最短路相邻不能经过相同的点。
  • 最短路源点不同。

处理办法

  • 维护(最多不合法数量 + 1)个最值,要求最值的特征值两两不同。
  • 每次松弛(转移),分类讨论:
    • 如果最值集合中没有当前特征值:尝试用当前最值替换集合中的最劣解。
    • 如果最值集合中有当前特征值:直接更新对应最值。
  • 如果是 DP,直接朴素维护或平衡树维护。
  • 如果是 dij,每个集合中的最值对应一个点,每次松弛最多更新一个点的 $dis$,及时将其放入队列。

例题

最短路,但是每个点有点权,要求路径的任何一个前缀的点权异或和不为 0。

solution

直接做就可以了,此题当然可以加强,但我懒得。

Released under the MIT License.