Floyd与Johnson最短路

正题

这两个为什么要放在一起讲?
这两个都可以处理有负边的多源最短路.
但是 F l o y d Floyd Floyd 好像比 J o h n s o n Johnson Johnson 最短路的用处更大,尤其是在最小环问题上。

Floyd

简简单单的两行代码,蕴藏了很多玄机?

for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
	f[i][j]=min(f[i][j],f[i][k]+f[k][j]);

首先第一行枚举的是中间的转移点,第 k k k 次处理完之后,你就可以得到端点为 x x x y y y ,中间转移点只在 [ 1 , k ] [1,k] [1,k] 的最短路.

根据这个性质,我们可以做很多事情,因为这代表着每个 k k k 之间都是独立的,我们甚至可以以想要的顺序枚举这个 k k k ,那么每一时刻得到的最短路就是端点为 x x x y y y ,中间转移点为 已枚举过的点 的最短路.

所以我们可以带个 log ⁡ \log log 用线段树分治来做类似于 转移点不为k的多源最短路可删点/加点可离线多源最短路

无向图的最小环也可以用 F l o y d Floyd Floyd 很好地解决(先排除自环和重边,其次不讨论两元环),可以先看看具体代码:

for(int k=1;k<=n;k++){
	for(int i=1;i<k;i++) 
		for(int j=1;j<i;j++) 
			ans=min(ans,dis[k][i]+dis[j][k]+f[i][j]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}

如果为有向图,那么就将第三行的 i i i 改成 k k k 。(因为允许二元环了,而且不能确定 k k k 连接的两个点的大小关系)。
看起来好像就加了那三行,因为处理 k k k 之前已经处理好了端点为 x , y x,y x,y ,中间点为 [ 1 , k ) [1,k) [1,k) 的最短路,所以现在如果能找到一条 x → y x\to y xy 的路径,满足路径上的全部点都 < k <k <k,那么就可以用 k k k 来更新,每一个环会在环的最大端点被算多次。所以只能做取 min ⁡ \min min 类似的操作

Jhonson最短路

也是多源最短路的一种,如果没有负边,那么就直接对 n n n 个点跑 D i j k s t r a Dijkstra Dijkstra 即可,否则我们可以用 S P F A SPFA SPFA 先跑出每个点的距离,根据这个重设边权,再跑 D i j k s t r a Dijkstra Dijkstra 。由于 S P F A SPFA SPFA 的时间复杂度为 O ( n m ) O(nm) O(nm) ,而对于每个点跑 D i j k s t r a Dijkstra Dijkstra 的时间复杂度是 O ( n ( n + m ) log ⁡ m ) O(n(n+m)\log m) O(n(n+m)logm) , 所以 S P F A SPFA SPFA 的时间复杂度不在瓶颈上, J h o n s o n Jhonson Jhonson 最短路的时间复杂度也是 O ( n ( n + m ) log ⁡ m ) O(n(n+m)\log m) O(n(n+m)logm)

说说怎么重设边权才合理,首先选所有缩强联通分量成 D A G DAG DAG 后,在所有入度为 0 0 0 的联通块中各找一个点作为起始点(无向图则不用考虑,因为必缩成一个点,这也是为什么 J h o n s o n Jhonson Jhonson 最短路一般用在无向图的原因),假设初始点集为 S S S ,跑出其他点到 S S S 的最短距离 d i s [ i ] dis[i] dis[i],对于一条边 ( x , y , c ) (x,y,c) (x,y,c),重设边权为 d i s [ x ] − d i s [ y ] + c dis[x]-dis[y]+c dis[x]dis[y]+c ,因为 d i s [ y ] ≤ d i s [ x ] + c dis[y]\leq dis[x]+c dis[y]dis[x]+c,所以有重设后的边权 ≥ 0 \geq0 0 ,可以跑 D i j k s t r a Dijkstra Dijkstra ,对于一条路径而言,中间的 d i s dis dis 会两两相消,只剩下 d i s [ u ] − d i s [ v ] + ∑ c dis[u]-dis[v]+\sum c dis[u]dis[v]+c ,前面两项是定值,要求式子最小相当于要求最后一项最小。

J o h n s o n Johnson Johnson 是个处理有负边多源最短路的强有力的工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值