Floyd

为数不多的全源最短路算法,全源即,全部点为原点,即算出任意两个点之间的最短路径。
前提条件,没有负环。可有负权。
因为中心思想是动态规划,所以有很强的性质,做题的时候注意利用。

中心思想

中心思想为动态规划。
现在我们设 f[k][i][j] 表示从点 i i i 到点 j j j,只经过 1 1 1 k k k 的最短距离。

初始化,当 k = 0 k=0 k=0f[0][i][j] 的值仅为 i i i j j j 的边权, 0 0 0 或者 + ∞ +\infty +。当 i = j i = j i=j 时为 0 0 0,即到自身的距离为 0 0 0;当 i ≠ j i\not=j i=j 时, i i i j j j 之间有权值则为权值,无权值则为 + ∞ +\infty +
k ≥ 1 k\ge1 k1 时,有 f[k][i][j] = min(f[k - 1][i][j], f[k - 1][i][k] + f[k - 1][k][j]) 即经过点 k k k 看是否能松弛 i i i j j j 之间的距离。

时间复杂度也显而易见 O ( n 3 ) O(n^3) O(n3)

注意本质。

正确性

本质是动态规划,正确性显而易见,当 k = n k=n k=n 时,即可以经历所有点去松弛,自然可以得到最短路径,但是如果有负环,因为算法不能无限进行负环操作,因此,不能得出负无穷。

实际操作

  1. 初始化之后,从 1 1 1 n n n 枚举 k k k 的大小
  2. 枚举 i i i
  3. 枚举 j j j
  4. 根据转移方程,进行转移
  5. 重复上述操作

代码

很简单就三个 for

for (int i = 1; i <= n; i ++ )
	for (int j = 1; j <= n; j ++ )
		f[0][i][j] = g[i][j];

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

因为是动态规划,转移又只涉及上一维,所以可以优化一维空间。
最常用的也是这种。

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

相关好题

关于 Floyd 就不得不提到这题P1119 灾后重建,非常经典的好题,涉及了 Floyd 的本质,只用这题就可以彻底了解 Floyd。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值