http://developer.51cto.com/art/201403/433874.htm(作者:坐在马桶上看算法)
个人觉得这个大神写得很好,所以放在这里参考一下
Floyd算法:
一、定义:
Floyd算法是用于解决多源最短路径的算法,即可以求任意两个节点之间的最短路径,由Robert W. Floyd(罗伯特·弗洛伊德)于1962年发表在“Communications of the ACM”上。
二、描述:
对于任意两个节点来说,假设不能经过第三个节点,那么最短路径就是初始赋值
假设只能通过第一个节点,那么比较从i到j与从i到1再到j的路径长度,取最小,由此更新所有节点间的路径
再看假设只能通过第一、二个节点,更新所有节点间路径
能通过第一、二、三个节点…直到能通过所有节点
最后dist[i][j]存的就是从i到j的最短路径长度。
三、步骤:
1.定义dist[maxn][maxn]来记录最短路径,先根据题意初始化,有权值则赋权值,无权值则赋无穷,节点相同赋0
2.三重循环更新节点间的最短路径dist[i][j],需记住中间节点的循环在最外层。
3.最后dist[i][j]存的就是从i到j的最短路径长度
四、核心代码(只有五行):
for(k=1;k<=s;k++)
for(i=1;i<=s;i++)
for(j=1;j<=s;j++)
if(dist[i][j]>dist[i][k]+dist[k][j])
dist[i][j]=dist[i][k]+dist[k][j];
五、例题:
1、find the safest road-hdu1596
题目概述:8600进行星球旅游,希望路线的安全系数最高,求任意输入的两个星球之间的最高安全系数。因为起点终点不确定,所以很明显是求多源最短路径,用Floyd算法。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
double dist[1005][1005]={0};
int main()
{
int n,i,j,k;
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%lf",&dist[i][j]);
for(k=0;k<n;k++)
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(dist[i][k]*dist[k][j]>dist[i][j])
dist[i][j]=dist[i][k]*dist[k][j];
int q;
scanf("%d\n",&q);
while(q--)
{
int b,c;
scanf("%d%d",&b,&c);
if(dist[b-1][c-1])
printf("%.3lf\n",dist[b-1][c-1]);
else
printf("What a pity!\n");
}
}
return 0;
}
2、HDU Today-hdu2112
题目概述:帮徐总坐公交,输出能到达目的地的最短时间,不能就输出-1。这个题目已经指出了起点和终点,应该是用dijkstra算法的,但是我比较喜欢Floyd些,另外这个题目还有几个坑点,如起点终点相同、起点被孤立、输出-1等等,但在我看来最坑最坑的地方就是题目明明是个有向图,却非得弄成无向图来做,害我wa了七八次!!!
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 99999999
#define maxn 10005
int t; //记录出现的总站数
char station[160][35];//用来记录出现过的站名
int dist[160][160]; //用来记录节点间的最短路径
int record(char x[])//将站名编号,出现过就返回对应编号,没出现过就用station[][]记录,并编号,方便后面用Floyd
{
int i=1;
for(i=1;i<t;i++)
{
if(strcmp(station[i],x)==0)
break;
}
if(i==t)
{
strcpy(station[i],x);
t++;
}
return i;
}
int main()
{
int n,i,j,k,c,station1,station2,s=160;
char start[35],End[35];
char a[35],b[35];
while(scanf("%d",&n)!=EOF&&n!=-1)
{
t=1;//每一次都将总站数初始为1
memset(station,0,sizeof(station));//每一次都将station[][]清空
scanf("%s%s",start,End);
for(i=1;i<=s;i++)
for(j=1;j<=s;j++)
if(i==j) dist[i][j]=0;
else dist[i][j]=INF;//初始dist
for(i=1;i<=n;i++)
{
scanf("%s%s%d",a,b,&c);
station1=record(a);
station2=record(b);
if(c<dist[station1][station2]&&c<dist[station2][station1])/*我觉得这里应该加上判断,不过不加也没错,可能是题目规定了没有多重边吧,也可能是杭电比较水*/
dist[station1][station2]=dist[station2][station1]=c;/*这题题目有毒,明明是个有向图非要按无向图来做*/
}
station1=record(start);
station2=record(End);
for(k=1;k<=s;k++)//Floyd算法
for(i=1;i<=s;i++)
for(j=1;j<=s;j++)
if(dist[i][j]>dist[i][k]+dist[k][j])
dist[i][j]=dist[i][k]+dist[k][j];
if(dist[station1][station2]<INF)
printf("%d\n",dist[station1][station2]);
else
printf("-1\n");
}
return 0;
}