任意两点间的最短路问题 Floyd-Warshall算法
这一算法与之前的Bellman-F=Ford算法一样,都可以判断负环
只需要检查dp [i] [j] 是负数的顶点i即可
// 求解任意两点间的最短路径问题 // Floyed-Warshall算法 // 复杂度O(N^3),N为顶点数 #include <cstdio> #include <iostream> using namespace std; // 用dp的思路来求解 // dp[k][i][j]:从i到j,只利用前K个节点的最短路 // dp[k][i][j]=dp[k-1][i][k] + dp[k-1][k][j] // 由于后一层所需的,都来自前一层,而前一层所需 // 然后在考虑循环顺序,定k,并且维护最小,所以中间元素必定使用之前维护的在k行k列的元素 // 而维护最小值时,k行k列元素,在循环中,加和一定大于原来的值(否则存在d[i][j]<0,存在负圈) // 所以维护最小值时不更新,依旧是上一列表中的值 // 所以dp数组可以降维进行运算 const int max_N = 200+2; const int max_E = 10000+2; const int INF = 1e9; int dp[max_N][max_N]; int N,E; void floyd_warshall() { for(int k=0;k<N;++k) { for(int i=0;i<N;++i) { for(int j=0;j<N;++j) { dp[i][j]=min( dp[i][j],dp[i][k]+dp[k][j] ); } } } } int main() { scanf("%d %d",&N,&E); int a,b,c; for(int i=0;i<N;++i) { for(int j=0;j<N;++j) { if(i==j) { dp[i][j]=0; } else { dp[i][j]=INF; } } } for(int i=0;i<E;++i) { scanf("%d %d %d",&a,&b,&c); dp[a][b]=c; // 无向图 dp[b][a]=c; } floyd_warshall(); for(int i=0;i<N;++i) { for(int j=0;j<N;++j) { printf("%d ",dp[i][j]); } printf("\n"); } return 0; } /* 7 10 0 1 2 0 2 5 1 2 4 1 3 6 1 4 10 2 3 2 3 5 1 4 5 3 4 6 5 5 6 9 0 2 5 7 11 8 16 2 0 4 6 10 7 15 5 4 0 2 6 3 11 7 6 2 0 4 1 9 11 10 6 4 0 3 5 8 7 3 1 3 0 8 16 15 11 9 5 8 0 */