Defination
-
对于一个图(管他是有向图,无向图,管他有没有环,管他边权为负与否),没有负环.
-
d i s [ i ] [ j ] dis[i][j] dis[i][j]表示 i i i出发,到 j j j最短路,满足 d i s [ i ] [ v ] ≤ d i s [ i ] [ u ] + w [ u , v ] dis[i][v]\le dis[i][u]+w[u,v] dis[i][v]≤dis[i][u]+w[u,v]
Algorithm
总结一下各种算法的性质:
1. D I J K S T R A DIJKSTRA DIJKSTRA
我的最爱~~~
-
基于贪心,以点为基点“松弛”,要求边权非负,复杂度很稳定,最短路计数方便,好想又好写!!
-
实现方式:
-1.堆优化排序。( priority-queue \text{priority-queue} priority-queue),要打一个 v i s vis vis标记:一个点出队一次。
复杂度: O ( ( n + m ) l o g ( n + m ) ) O((n+m)log(n+m)) O((n+m)log(n+m)),后面那个log并不会被卡边数。-2.set优化排序。 e r a s e erase erase代替 v i s vis vis
复杂度: O ( ( n + m ) l o g n ∗ set常数 ) O((n+m)logn*\text{set常数}) O((n+m)logn∗set常数),不见得快多少,主要是好写。 -
扩展: J o h n s o n Johnson Johnson算法让 d i j dij dij也可以跑负边权最短路。
-1,建立 源点 S S S, ∀ i , l i n k ( S , i , 0 ) \forall \ i,link(S,i,0) ∀ i,link(S,i,0),用 s p f a spfa spfa跑一边 S S S为起点的最短路,即为 D i D_i Di。-2,修改边权。 ∀ e d g e i , w i = w i + ( D u − D v ) \forall \ edge_i,w_i=w_i+(D_u-D_v) ∀ edgei,wi=wi+(Du−Dv)。
-3, d i j dij dij跑原图最短路, d i s [ u ] [ v ] = d i s [ u ] [ v ] − ( D [ u ] − D [ v ] ) dis[u][v]=dis[u][v]-(D[u]-D[v]) dis[u][v]=dis[u][v]−(D[u]−D[v])。
2.SPFA
-
本质是以边为单位。 v i s vis vis标记改为"队列中一个点唯一存在,不重复"。
-
复杂度: O ( m ) O(m) O(m)~ O ( n ∗ m ) O(n*m) O(n∗m)(卡spfa是一个出题人的自我修养)
-
各种优化: 1.双端队列,和队首比较,选最优。2.堆优化决策点。(负权图会被卡成 O ( n ∗ m ∗ l o g n ) O(n*m*logn) O(n∗m∗logn),真好笑)
-
扩展: 判负环: 一个点被松弛次数超过 n − 1 n-1 n−1次,说明有负环。可用 d f s dfs dfs迭代加深优化实现,或者来一个 r a n d o m − s h u f f l e random-shuffle random−shuffle。。
3.FLOYD
-
本质:动态规划: d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k],只经过编号 ≤ k \le k ≤k的点, i , j i,j i,j最短路。
-
d p [ i ] [ j ] [ k ] = m i n ( d p [ i ] [ j ] [ k − 1 ] , d p [ i ] [ k ] [ k − 1 ] + d p [ j ] [ k ] [ k − 1 ] dp[i][j][k]=min(dp[i][j][k-1],dp[i][k][k-1]+dp[j][k][k-1] dp[i][j][k]=min(dp[i][j][k−1],dp[i][k][k−1]+dp[j][k][k−1].
-
复杂度: O ( n 3 ) O(n^3) O(n3)
-
扩展:由于是动态规划,可以解决一些其他的问题。
-1.传递闭包。 f [ i ] [ j ] ∣ = f [ i ] [ k ] & f [ k ] [ j ] f[i][j]\ |=\ f[i][k]\And f[k][j] f[i][j] ∣= f[i][k]&f[k][j]
-2.最小环: 最小环: d i s ] [ i ] [ j ] ( 不 经 过 e d g e [ i ] [ j ] ) + e d g e [ i ] [ j ] dis][i][j](不经过edge[i][j])+edge[i][j] dis][i][j](不经过edge[i][j])+edge[i][j],显然可以用 f l o y d floyd floyd的性质。
-3.规定边数的最短路 ∣ e d g e ∣ ≤ 1 e 9 |edge|\le1e9 ∣edge∣≤1e9,把边看作矩阵,矩阵相乘即为 A r ∗ A c = A r + c A^r\ *\ A^c=A^{r+c} Ar ∗ Ac=Ar+c
Application
1.单源最短路,单源 的理解:一个集合到另一个之间的最短路。
详见:GZOI2019旅行者
2.最短路树:每个点只会由一个点更新,我们显然可以连成最短路树。最短路树不只能确定最短路关系。(safe trave) 一些简单的问题可以通过最短路树解决。(最小环长度)
3.边权为1时,最短路树演变成bfs树。可以借以分析最终的最短路情况。(比如在bfs树上做一个dp(10.9测试 期望dp)