Floyd算法(弗洛伊德算法) 百度百科
核心代码
for(int k=1; k<=NODE; ++k)//对于每一个中转点
for(int i=0; i<=NODE; ++i)//枚举源点
for(int j=0; j<=NODE; ++j)//枚举终点
if(distmap[i][j]>distmap[i][k]+distmap[k][j])//不满足三角不等式
{
distmap[i][j]=distmap[i][k]+distmap[k][j];//更新
path[i][j]=k;//记录路径
}状态转移方程
其状态转移方程如下: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]};
map[i,j]表示i到j的最短距离,K是穷举i,j的断点,map[n,n]初值应该为0,或者按照题目意思来做。
当然,如果这条路没有通的话,还必须特殊处理,比如没有map[i,k]这条路。
时间复杂度:O(n^3);
Floyd算法适用于APSP(All Pairs Shortest Paths,多源最短路径),是一种动态规划算法,稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法,也要高于执行V次SPFA算法。
优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单。
缺点:时间复杂度比较高,不适合计算大量数据。
a) 初始化:D[u,v]=A[u,v]
b) For k:=1 to n
For i:=1 to n
For j:=1 to n
If D[i,j]>D[i,k]+D[k,j] Then
D[i,j]:=D[i,k]+D[k,j];
c) 算法结束:D即为所有点对的最短路径矩阵
C语言
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
#include<stdio.h>#include<stdlib.h>#define max 1000000000int d[1000][1000],path[1000][1000];int main(){int i,j,k,m,n;int x,y,z;scanf("%d%d",&n,&m);for(i=1;i<=n;i++)for(j=1;j<=n;j++){ d[i][j]=max; path[i][j]=j;}for(i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);d[x][y]=z;d[y][x]=z;}for(k=1;k<=n;k++)for(i=1;i<=n;i++)for(j=1;j<=n;j++){if(d[i][k]+d[k][j]<d[i][j]){ d[i][j]=d[i][k]+d[k][j]; path[i][j]=path[i][k]; }}for(i=1;i<=n;i++)for(j=1;j<=i;j++) if (i!=j) printf("%d->%d:%d\n",i,j,d[i][j]);int f,en;scanf("%d%d",&f,&en);while (f!=en){ printf("%d->",f); f=path[f][en];}printf("%d\n",en);return 0;} |
C++语言
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include<iostream>#include<vector>using namespace std;const int &INF=100000000;void floyd(vector<vector<int> > &distmap,//可被更新的邻接矩阵,更新后不能确定原有边 vector<vector<int> > &path)//路径上到达该点的中转点//福利:这个函数没有用除INF外的任何全局量,可以直接复制!{ const int &NODE=distmap.size();//用邻接矩阵的大小传递顶点个数,减少参数传递 path.assign(NODE,vector<int>(NODE,-1));//初始化路径数组 for(int k=1; k!=NODE; ++k)//对于每一个中转点 for(int i=0; i!=NODE; ++i)//枚举源点 for(int j=0; j!=NODE; ++j)//枚举终点 if(distmap[i][j]>distmap[i][k]+distmap[k][j])//不满足三角不等式 { distmap[i][j]=distmap[i][k]+distmap[k][j];//更新 path[i][j]=k;//记录路径 }}void print(const int &beg,const int &end, const vector<vector<int> > &path)//传引用,避免拷贝,不占用内存空间 //也可以用栈结构先进后出的特性来代替函数递归 { if(path[beg][end]>=0) { print(beg,path[beg][end],path); print(path[beg][end],end,path); } else cout<<"->"<<end;}int main(){ int n_num,e_num,beg,end;//含义见下 cout<<"(不处理负权回路)输入点数、边数:"; cin>>n_num>>e_num; vector<vector<int> > path, distmap(n_num,vector<int>(n_num,INF));//默认初始化邻接矩阵 for(int i=0,p,q; i!=e_num; ++i) { cout<<"输入第"<<i+1<<"条边的起点、终点、长度(100000000代表无穷大,不联通):"; cin>>p>>q; cin>>distmap[p][q]; } floyd(distmap,path); cout<<"计算完毕,可以开始查询,请输入出发点和终点:"; cin>>beg>>end; cout<<"最短距离为"<<distmap[beg][end]<<",打印路径:"<<beg; print(beg,end,path);} |

浙公网安备 33010602011771号