Floyd-多源最短路径
今天抽个时间复习一下Floyd——多源最短路径
所谓“多源”就是求出每个点到另外所有点的最短距离,所以说比不上迪杰斯特拉的速度,时间复杂度也是到了O(n^3)。
不过写起来就很简单,核心就五行代码,而且也容易理解。
就比如说给了如下数据
在这个图中,没有给权重的边先看成正无穷,想要求i点到j点的最短距离就是看看能不能通过寻找中间点k使得i到k的距离加上k到j的距离小于i到j的距离。
即:
if(v[i][j]>v[i][k]+v[k][j])
{
v[i][j]=v[i][k]+v[k][j];
}
如上图1到5的距离是100,当中间点为2时,100>1+80,这个时候v[1][5]就会更新为81;
所以说更新所有点就是要在判断条件外面加两个循环,然后把中间点所有情况也考虑一遍就要再加一个循环。
所以核心代码就下面五行。
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(v[i][j]>v[i][k]+v[k][j])
v[i][j]=v[i][k]+v[k][j];
但是不能解决带负权回路的图,这样就找不到最小距离。
下面给完整代码和测试用例
#include<bits/stdc++.h>
using namespace std;
int v[505][505];
#define inf 99999;
int main()
{
int n,m,t1,t2,t3;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i==j)v[i][j]=0;
else
v[i][j]=inf;
for(int i=0;i<m;i++)
{
cin>>t1>>t2>>t3;
v[t1][t2]=v[t2][t1]=t3;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(v[i][j]>v[i][k]+v[k][j])
v[i][j]=v[i][k]+v[k][j];
cout<<endl<<endl;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
printf("%-5d",v[i][j]);
cout<<endl;
}
return 0;
}
6 11
3 4 70
1 2 1
5 4 50
2 6 50
5 6 60
1 3 70
4 6 60
3 6 80
5 1 100
2 4 60
5 2 80
这里因为我用的是无向图所以数据是对称的。