HDU 1874 畅通工程续 (Floyd)
前天队里介绍了单源最短路径算法,一共涉及以下四种:Floyd-Warshall, Dijkstra, Bellman-Ford, SPFA
Floyd 用来找出每对点之间的最短距离。需要一个邻接矩阵存储边。通过考虑最佳子路径实现找最短路径。
算法实现:
使用一个邻接矩阵存储边权值,两两之间能访问的必为一个有限的数,不能访问则为无穷大(用2^29代替)。注意自身和自身距离为0。
对于一对顶点 u 和 v,看看是否存在一个断点 w 使得从 u 经过 w 到 v 比已知的路径更短(包含原始输入中从 u 直接到 v 的路程)。
对所有顶点进行如上松弛操作,得到的结果是两点之间的最短路程,也可判断两点是否连通。
以上只是自己的理解,《离散数学》中传递闭包和Warshall一节有更详细证明。
算法缺点:
普通的Floyd算法时间复杂度为O(n^3),对于数据较多的情况容易TLE。但解决本题 HDU 1874 完全足够。
后记:
提交了n把WA掉n把,百思不得其解,于是放某度知道询问。后来是 chenwenwen0210 指出的问题,向他表示感谢。
至于原因,1<<29给敲成了1<<9,居然没检查出来。。。看来我还是太粗心了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 using namespace std; 3 4 const int INF = 1 << 29; 5 int n, m, map[1000][1000]; 6 7 void init() 8 { 9 for(int i = 0; i < n; i++) 10 for(int j = 0; j < n; j++) 11 map[i][j] = (i == j) ? 0 : INF; 12 } 13 14 void floyd() 15 { 16 for(int k = 0; k < n; k++) 17 for(int i = 0; i < n; i++) 18 for(int j = 0; j < n; j++) 19 map[i][j] = min(map[i][k] + map[k][j], map[i][j]); 20 } 21 22 int main() 23 { 24 while(scanf("%d%d", &n, &m) != EOF) 25 { 26 int start, end; 27 init(); 28 while(m--) 29 { 30 int a, b, len; 31 scanf("%d%d%d", &a, &b, &len); 32 if(len < map[a][b]) 33 map[a][b] = map[b][a] = len; //主要是考虑到有重边的可能(浪费资源,囧) 34 } 35 scanf("%d%d", &start, &end); 36 floyd(); 37 printf("%d\n", (map[start][end] < INF) ? map[start][end] : -1); 38 } 39 return 0; 40 }