Flody算法是一种多源最短路径算法。(即每个点到其他点之间的最短路径)
1.问题引出
有四个城市1,2,3,4, 8条街道(分别表明了路径长度),要求每个城市到其他城市的最短路径。
用 n 代表城市个数,m 代表城市道路的个数。
2.思路引导
首先我们来存储这些数据,用一个二维数组,map[105][105].(map[ i ][ j ],代表从地点 i 到 j 的距离是多少,
1.建立数组map[105][105],并初始化数组。
(这里我们定义两种距离,自己到自己的距离为0,自己到其他人的距离为 ∞,如1到1为0, 1到2,3,4为 ∞。)
int map[105][105]; //创建数组
for(int i=1;i<=n;i++) //n代表城市个数
for(int j=1;j<=n;j++)
{
if(i==j)map[i][j] = 0;
else map[i][j] = INF //这里的INF是预定义的 ,如 #define INF 65535
2.输入数据:
首先输入测试用例的个数,
//n代表城市个数,m代表道路个数。
while(cin >> n >> m){
/*
初始化代码。。。
*/
//Input data
for(int i=0;i<m;i++) //m条道路
{
int a,b,c;
cin >> a >> b >> c;
if(c < map[a][b]) //本来可以不用写这一行的,但是某些测试用例,会给你重复数据,
map[a][b] = c; //如2 3 2,2 3 4(2到3的距离为2,2到3的距离为4,直接改就error
}
输入后结果如图:
3.直接Flody算法。
当然算法前先介绍一下基本知识,缩短路径可以用三个点来缩短,需要松弛操作。
松弛点:
比如从1->2的距离为2, 3->1的距离为7, 3->2未直接连接,距离为无穷大,则以1为松弛点,3->2的距离可以改为更小的数9(2+7),直接更新。其他点类似。
/code形式:map[3][2] = map[3][1] + map[1][2];/
同样的,还可以以1为松弛点对其他道路进行更新。1松弛完后,结果如下:
同理,可以对2,3,4点分别当作松弛点进行松弛,松弛操作每次需要3个点即可。
于是可以将代码整理为如下:其中k点为松弛点,如k = 1,i = 3, j = 2,则是以1为松弛点,从3到2 判断是否能够松弛,如果距离比松弛后的距离大,则将距离改为松弛后的距离。
即 if ( map[i][j] > map[i][k] + map[k][j] ) map[i][j] = map[i][k] + map[k][j];
Floyd完整代码:
void Floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(map[i][j] > map[i][k]+map[k][j])
map[i][j] = map[i][k]+map[k][j];
}
4.输出距离:
比如题目让输出,从1点到4点的距离,则直接输出map数组的内容,即 map[1] [4].
cout << map[1][4] << endl;
3测试题与完整代码:
测试题:HDU - 2544 最短路
完整代码:
#include <iostream>
#define INF 655355
using namespace std;
int mp[105][105];
int n,m; ///n表示地点的个数,m表示路线个数
void Floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j] > mp[i][k]+mp[k][j])
mp[i][j] = mp[i][k]+mp[k][j];
}
int main()
{
while(cin >> n >> m)
{
if(m==0&&n==0)break;
//初始化
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
mp[i][j] = 0;
else
mp[i][j] = INF;
}
}
//INPUT
for(int i=0;i<m;i++)
{
int a,b,c;
cin >> a >> b >> c;
///防止有重复路径
if(c < mp[a][b])
mp[a][b] = mp[b][a] = c;
}
//Floyd
Floyd();
//Output
cout << mp[1][n] <<endl;
}
return 0;
}