您的位置:首页 > 其它

多源最短路径Floyd算法

2016-03-31 19:54 417 查看
多源最短路径是求图中任意两点间的最短路,采用动态规划算法,也称为Floyd算法。将顶点编号为0,1,2...n-1首先定义dis[i][j][k]为顶点 i 到 j 的最短路径,且这条路径只经过最大编号不超过k的顶点。于是我们最终要求的是dis[i][j][n-1].状态转移方程如下:

dis[i][j][k]=min{dis[i][j][k-1],dis[i][k][k-1]+dis[k][j][k-1]};

状态转移方程的解释:在计算dis[i][j][k]的时候,我们考虑 i 到 j 是否要经过顶点 k ,若不经过顶点 k ,那么结果就是 i 到 j 的最大路径经过的最大顶点不超过 k-1,也就是dis[i][j][k-1].倘若 i 到 j 经过顶点 k,那么i到j可以分为两部分之和,即 i 到k 和 k 到 j.这时候子问题最优解是 dis[i][k][k-1]和dis[k][j][k-1],这种情况下得到的原问题最优解是dis[i][k][k-1]+dis[k][j][k-1].所以综合起来: dis[i][j][k]=min{dis[i][j][k-1],dis[i][k][k-1]+dis[k][j][k-1]};

在实现的时候没有必要使用三维数组。可以采用覆盖的方法:从k=0 to n-1 来计算,状态方程改变如下:

dis[i][j]=min{dis[i][j],dis[i][k]+dis[k][j]};

#include<iostream>
using namespace std;
#define MAX_NUMBER INT_MAX/2
#define MAX_SIZE 100
struct Graph {
int V, E;
int R[MAX_SIZE][MAX_SIZE];
};
int path[MAX_SIZE][MAX_SIZE];
int dis[MAX_SIZE][MAX_SIZE];
void Floyd(Graph G);
void PrintPath(int i, int j);
int main() {
Graph G;
int i, j, w,k;
cin >> G.V >> G.E;
for (i = 0; i < G.V; i++)
for (j = 0; j < G.V; j++) {
G.R[i][j] = (i == j ? 0 : MAX_NUMBER);
path[i][j]=i;    //假设i到j有直接路径
}
//--------------------------------初始化
for (k = 0; k < G.E; k++) {
cin >> i >> j >> w;
G.R[i][j] = G.R[j][i] = w;
}
Floyd(G);
for (i = 0; i < G.V; i++) {
for (j = 0; j < G.V; j++)
printf("%3d", dis[i][j]);
cout << endl;
}
printf("\n");
for (i = 0; i < G.V; i++) {
for (j = 0; j < G.V; j++)
printf("%3d", path[i][j]);
cout << endl;
}
PrintPath(0,9);
return 0;
}
void Floyd(Graph G) {
int i, j, k;
for (i = 0; i < G.V; i++)
for (j = 0; j < G.V; j++)
dis[i][j] = G.R[i][j];         //初始化
for (k = 0; k < G.V; k++)
for (i = 0; i < G.V; i++)
for (j = 0; j < G.V;j++)
if (dis[i][j]>dis[i][k] + dis[k][j]) {        //更新
path[i][j] = k;
dis[i][j] = dis[i][k] + dis[k][j];
}
}
void PrintPath(int i, int j) {
if (i==j) {
printf("%3d", i);
return;
}
PrintPath(i,path[i][j]);
printf("%3d", j);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: