Floyd算法
传送门:
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 }