多源最短路径Floyd算法

     多源最短路径是求图中任意两点间的最短路,采用动态规划算法,也称为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]};

 1 #include<iostream>
 2 using namespace std;
 3 #define MAX_NUMBER INT_MAX/2
 4 #define MAX_SIZE 100
 5 struct Graph {
 6     int V, E;
 7     int R[MAX_SIZE][MAX_SIZE];
 8 };
 9 int path[MAX_SIZE][MAX_SIZE];
10 int dis[MAX_SIZE][MAX_SIZE];
11 void Floyd(Graph G);
12 void PrintPath(int i, int j);
13 int main() {
14     Graph G;
15     int i, j, w,k;
16     cin >> G.V >> G.E;
17     for (i = 0; i < G.V; i++)
18         for (j = 0; j < G.V; j++) {
19             G.R[i][j] = (i == j ? 0 : MAX_NUMBER);
20             path[i][j]=i;    //假设i到j有直接路径
21         }
22     //--------------------------------初始化
23     for (k = 0; k < G.E; k++) {
24         cin >> i >> j >> w;
25         G.R[i][j] = G.R[j][i] = w;
26     }
27     Floyd(G);
28     for (i = 0; i < G.V; i++) {
29         for (j = 0; j < G.V; j++)
30             printf("%3d", dis[i][j]);
31         cout << endl;
32     }
33     printf("
");
34     for (i = 0; i < G.V; i++) {
35         for (j = 0; j < G.V; j++)
36             printf("%3d", path[i][j]);
37         cout << endl;
38     }
39     PrintPath(0,9);
40     return 0;
41 }
42 void Floyd(Graph G) {
43     int i, j, k;
44     for (i = 0; i < G.V; i++)
45         for (j = 0; j < G.V; j++)
46             dis[i][j] = G.R[i][j];         //初始化
47     for (k = 0; k < G.V; k++)
48         for (i = 0; i < G.V; i++)
49             for (j = 0; j < G.V;j++)
50                 if (dis[i][j]>dis[i][k] + dis[k][j]) {        //更新
51                     path[i][j] = k;
52                     dis[i][j] = dis[i][k] + dis[k][j];
53                 }
54 }
55 void PrintPath(int i, int j) {
56     if (i==j) {
57         printf("%3d", i);
58         return;
59     }
60     PrintPath(i,path[i][j]);
61     printf("%3d", j);
62 }
原文地址:https://www.cnblogs.com/td15980891505/p/5342507.html