Floyd算法

谁都会走 提交于 2020-01-19 15:28:29

传送门:

 Dijkstra

 Bellman-Ford

 SPFA

 Floyd

1.算法思想:

定义一个n阶方阵序列:A(-1) A(0) A(1) A(2) ....... A(n-1)

A(-1) [i][j]表示顶点Vi到顶点Vj的直接边的长度,A(-1) 就是邻接矩阵Edge[n][n]

A(0) [i][j]表示顶点Vi到顶点Vj,中间顶点(如果有,则)是V0的最短路径长度

A(1) [i][j]表示顶点Vi到顶点Vj,中间顶点序号不大于1的最短路径长度

A(2) [i][j]表示顶点Vi到顶点Vj,中间顶点序号不大于2的最短路径长度

A(n-1) [i][j]表示顶点Vi到顶点Vj最短路径长度

允许带有负权值的边,但不能有负权值回路。

2.代码实现

输入:

4 8
0 1 1
0 3 4
1 2 9
1 3 2
2 0 3
2 1 5
2 3 8
3 2 6

输出:

0->1    1       0->1
0->2    9       0->1->3->2
0->3    3       0->1->3
1->0    11      1->3->2->0
1->2    8       1->3->2
1->3    2       1->3
2->0    3       2->0
2->1    4       2->0->1
2->3    6       2->0->1->3
3->0    9       3->2->0
3->1    10      3->2->0->1
3->2    6       3->2

递推式a[i][j] = min(a[i][j], a[i][k] + a[k][j])

如果只是判断连通性,可改成a[i][j] |= a[i][k] & a[k][j];

此处存路径是按照倒叙存储路径path[i][j]表示从顶点vi到vj的最短路径上顶点j的前一个点的序号,这里有正序存路径使得字典序最小,而且这里必须在初始化的时候初始化path,如果有边就要初始化。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #include<stack>
 8 #include<map>
 9 #include<set>
10 #include<sstream>
11 using namespace std;
12 typedef long long ll;
13 const int maxn = 1000 + 10;
14 const int INF = 1 << 25;
15 int T, n, m, cases;
16 int Map[maxn][maxn];//存图
17 int path[maxn][maxn];//存路径,path[i][j]表示从顶点vi到vj的最短路径上顶点j的前一个点的序号
18 int a[maxn][maxn];//存最短路径长度
19 void Floyd()
20 {
21     for(int i = 0; i < n; i++)
22     {
23         for(int j = 0; j < n; j++)
24         {
25             for(int k = 0; k < n; k++)
26             {
27                 a[i][j] = Map[i][j];
28                 if(i != j && a[i][j] < INF)path[i][j] = i;//i到j有路径
29                 else path[i][j] = -1;//从i到j没有直接的路径
30             }
31         }
32     }
33     for(int k = 0; k < n; k++)
34     {
35         for(int i = 0; i < n; i++)
36         {
37             for(int j = 0; j < n; j++)
38             {
39                 if(k == i || k == j)continue;
40                 if(a[i][k] + a[k][j] < a[i][j])
41                 {
42                     a[i][j] = a[i][k] + a[k][j];
43                     path[i][j] = path[k][j];
44                 }
45             }
46         }
47     }
48     for(int i = 0; i < n; i++)
49     {
50         for(int j = 0; j < n; j++)
51         {
52             if(i == j)continue;
53             printf("%d->%d\t%d\t", i, j, a[i][j]);
54             stack<int>q;
55             int x = j;
56             while(x != -1)
57             {
58                 q.push(x);
59                 x = path[i][x];
60             }
61             cout<<q.top();
62             q.pop();
63             while(!q.empty())
64             {
65                 cout<<"->"<<q.top();
66                 q.pop();
67             }
68             cout<<endl;
69         }
70     }
71 }
72 int main()
73 {
74     cin >> n >> m;
75     for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)Map[i][j] = (i == j ? 0 :INF);
76     int u, v, w;
77     for(int i = 0; i < m; i++)
78     {
79         cin >> u >> v >> w;
80         Map[u][v] = w;
81     }
82     Floyd();
83     return 0;
84 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!