1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #define VERTEX 5
5 #define INF 99999
6 #define NIL -1
7
8 void print_all_pairs_shortest_path(int pi[][VERTEX], int i, int j)
9 {
10 if (i == j)
11 printf("%d, ", i);
12 else if (pi[i][j] == NIL)
13 printf("no path from %d to %d exists\n", i, j);
14 else {
15 print_all_pairs_shortest_path(pi, i, pi[i][j]);
16 printf("%d, ", j);
17 }
18 }
19
20 void print_matrix(int W[][VERTEX])
21 {
22 int i, j;
23 for (i = 0; i < VERTEX; i++)
24 for (j = 0; j < VERTEX; j++) {
25 if (j == 0)
26 printf("\n");
27 printf("%d\t", W[i][j]);
28 }
29 putchar('\n');
30 printf("========================================\n");
31 }
32
33
34 /*
35 结点编号:从 0 到 VERTEX-1
36
37
38 */
39 void floyd_warshall(int W[][VERTEX], int pi[][VERTEX])
40 {
41 int n = VERTEX;
42 int k, i, j;
43 /*
44 loop invariant:
45 结点编号i到编号j的
46 中间节点编号小于k的最短路径
47 存储在W[i][j]中
48
49 初始化k为0,所以中间结点小于0的最短路径,即没有中间结点的最短路径,即边的权重或INF存储在W中
50 */
51 for (k = 0; k < VERTEX; k++) {
52 for (i = 0; i < VERTEX; i++) {
53 for (j = 0; j < VERTEX; j++) {
54 /*
55 用宏模拟无穷大时,可能出现错误的最短路径更新
56 因为理论上无穷大加负数也是无穷大,但符号常量加负数小于符号常量,导致错误更新
57 添加更新最短路的条件 W[i][k] != INF && W[k][j] != INF,避免错误发生
58 */
59 if (W[i][j] > W[i][k]+W[k][j] && W[i][k] != INF && W[k][j] != INF) {
60 W[i][j] = W[i][k]+W[k][j];
61 pi[i][j] = pi[k][j];
62 }
63 }
64 }
65 printf("k = %d\n", k);
66 print_matrix(W);
67 print_matrix(pi);
68 }
69 }
70
71 int main()
72 {
73 int W[VERTEX][VERTEX] = {
74 {0, 3, 8, INF, -4},
75 {INF, 0, INF, 1, 7},
76 {INF, 4, 0, INF, INF},
77 {2, INF, -5, 0, INF},
78 {INF, INF, INF, 6, 0}
79 };
80
81 int pi[VERTEX][VERTEX] = {
82 {NIL, 0, 0, NIL, 0},
83 {NIL, NIL, NIL, 1, 1},
84 {NIL, 2, NIL, NIL, NIL},
85 {3, NIL, 3, NIL, NIL},
86 {NIL, NIL, NIL, 4, NIL}
87 };
88 print_matrix(W);
89 print_matrix(pi);
90 printf("========================================\n");
91 floyd_warshall(W, pi);
92 printf("========================================\n");
93 int i, j;
94 for (i = 0; i < VERTEX; i++)
95 for (j = 0; j < VERTEX; j++) {
96 printf("the shortest path from %d to %d is: ", i, j);
97 print_all_pairs_shortest_path(pi, i, j);
98 putchar('\n');
99 }
100 return 0;
101 }