floyd最短路径解法

         之前在解题过程中讲过的最短路算法DijkstraSPFA,但是,它们都是用来求单源最短路径的,比如说有一道题,先建一个图,然后要进行k次询问,问两个点的最短距离,那怎么办?用dijkstra或spfa跑k遍?显然不合理,如果k是10000,就已经受不了了,所以,就得用一种新的算法来解决。

好,下面有请我们今天的主角,floyd上场!

floyd的缺点是时间复杂度,跑一遍就是O(N^3),特别难受,在数据范围小的时候可以用,但稍微大一点,比如N=1e5,就直接爆掉了。但它的优点是只跑一遍就能求导全源最短路径,任意两个点之间都有了。但是你会发现,求全源最短路径,就是用dijkstra跑N遍,也就是O(NlogN)的时间复杂度跑n遍。就是O(N^2logN),哎,还是比floyd快。

呃,虽然floyd很垃圾,但是我还是要讲,因为它思路简单,代码实现也简单

floyd的大体思想是先找一个中间点,再找起点和终点,如果起点直接到终点的距离比经过中间点再到终点的距离大,就进行更新

拿上图举例,1->2的距离是7,1到3再到2明显要小,明显更优,肯定是先经过中间点更短,这时我们就更新。 

讲完了大体思路,就先提一下初始化,首先肯定是先把所有的点都初始化为正无穷大,这里就设0x3f3f3f3f了,因为是求最小值,然后就是把a[i][i]都设为1,因为自己到自己不需要走。

所有的都弄完了,就是问什么答什么了,如果a[x][y]的值大于1e9,就走不过去,注意,不是等于0x3f3f3f3f,因为中间可能会在找的途中出现微小的差异,但不是很大

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e2 + 5;
int a[N][N];
int n, m;
signed main() {
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (i == j) a[i][j] = 0;
			else a[i][j] = 0x3f3f3f3f;
	int u, v, w;
	for (int i = 1; i <= m; i++) {
		scanf("%lld%lld%lld", &u, &v, &w);
		a[u][v] = w;
	}
	for (int k = 1; k <= n; k++)
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				a[i][j] = min(a[i][j], a[i][k] + a[k][j]);
	int k;
	scanf("%lld", &k);
	int x, y;
	while (k--) {
		scanf("%lld%lld", &x, &y);
		if (a[x][y] >1e9)printf("impossible\n");//走不过去
		else printf("%lld\n", a[x][y]);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值