*钟皓曦老师授课*
常见最短路算法:
Floyd → O(n^3)
Bellman-Ford → O(nm)
Dijkstra → O(n^2+m)
Dijkstra-Heap → O((n+m)log(n+m))
SPFA → O(km) 随机图 (k一般为2) 可以判负环→若一个点进队列次数超过n次,则有负环。
O(nm) 精心构造的数据
→判断选用哪种算法:
if(n<=100) Floyd;
else if(无负权) Dijkstra-Heap;
else SPFA;
→
①单源最短路可以求解多源最短路问题。
②一点到另一点的最短路,最多经过n-1条边。
→证明:若路径包含的边数>=n,说明有环,我们可以去掉环之后直接走。因此最短路不存在环,也就最多只有n-1条边。
③求最短路一定无负环,求最长路一定无正环。但可以有正负权值的边。
次短路(次短简单路,即无重复点):
①枚举每一条边,删除后跑最短路,最后取min O(n*(n+m)log(n+m))。
②令dis[u][0]表示从起点到u的最短路,dis[u][1]表示从起点到u的次短路。
设W=dis[v][0]+e[i].w
当W∈左集合时 即新更新的最短路<之前最短路<之前次短路 ∴dis[v][1]=dis[v][0],dis[v][0]=W
当W∈中间集合时 即之前最短路<新更新的最短路<之前次短路 ∴dis[v][1]=W dis[v][0]不变
当W∈左集合时 即之前最短路<之前次短路<新更新的最短路 ∴dis[v][1]和dis[v][0]都不变
任何一个点的次短路可能有多段次短路组合而成,因此最终ans还要用次短路更新一遍。
PS.对于次短非简单路,用A*或ZEN(蒙特卡洛)算法,不考,而且我也不会。。。。
K短路:(目前不会。。。,但方法和上面类似)
差分约束:
给定n个变量,m个形如vi-vj</<=/>/>=/= k 的约束条件,令v1=0,求vn最小/最大是多少。
<=>n个点,m条边,从v1号点出发,问vn的最长路/最短路是多少。
例:v1-v3>=3 ①v1>=v3+3 根据最长路三角不等式,v3向v1连一条边权为3的边。建完图后跑最长路
②v3<=v1+(-3) 根据最短路三角不等式,v1向v3连一条边权为-3的边。建完图后跑最短路、
最大值<=>最短路 若存在负环,则最大值为无穷大
最小值<=>最长路 若存在正环,则最小值为无穷小
例:{v1-v2>=3 ; v2-v3>=3 ; v1-v3>=2 }
①最大值
{v2<=v1+(-3) ; v3<=v2+(-3) ; v3<=v1+(-2)}
∵从v1到v3的最短路为-6
∴ v3 max=-6
②最小值
{v1>=v2+3 ; v2>=v3+3 ; v1>=v3+2}
∵从v1到v3的最长路不存在
∴v3 min= -∞
常见连边方式:
vi-vj>=k -> vi>=vj+k or vj<=vi+(-k)
vi-vj>k -> vi-vj>=k+1
vi-vj=k -> vi-vj>=k&&vi-vj<=k -> vi>=vj+k&&vi<=vj+k 连两条边,形成一个零环,使两者最短/长路相等
vi-vj<=k
vi-vj<k ->vi-vj<=k-1