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,居然没检查出来。。。看来我还是太粗心了

View Code
 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  }

 

 

posted @ 2012-02-16 22:13  dgsrz  阅读(249)  评论(0编辑  收藏  举报