HDU 2544 最短路(Dijkstra和Floyd)
非常裸的最短路问题,昨天把Dijkstra的思想理解了下,发现和prim非常相似,都是用一个low数组记录到达每个点的最短距离,昨天WA了N次,发现数据中竟然有两个点的权值有的时候有好几个。。。杭电上这个题数据没有重边。
今天看了一下弗洛伊德,代码真的是挺简单,思想不是很理解。。。先代码实现,然后慢慢体会他的DP思路。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #define N 100000 5 int p[111][111],o[101],low[101]; 6 int main() 7 { 8 int n,m,i,j,k,sv,ev,w,min; 9 while(scanf("%d%d",&n,&m)!=EOF) 10 { 11 if(n == 0&&m == 0) break; 12 memset(o,0,sizeof(o)); 13 for(i = 1; i <= n; i ++) 14 for(j = 1; j <= n; j ++) 15 { 16 if(j != i) 17 p[i][j] = N; 18 else 19 p[i][j] = 0; 20 } 21 for(i = 1; i <= m; i ++) 22 { 23 scanf("%d%d%d",&sv,&ev,&w); 24 if(p[sv][ev] > w) 25 p[sv][ev] = w; 26 if(p[sv][ev] > w) 27 p[ev][sv] = w; 28 } 29 for(i = 1; i <= n; i ++) 30 { 31 low[i] = p[1][i]; 32 } 33 o[1] = 1; 34 for(i = 2; i <= n-1; i ++) 35 { 36 min = N; 37 for(j = 1; j <= n; j ++) 38 { 39 if(min > low[j]&&o[j] == 0) 40 { 41 min = low[j]; 42 k = j; 43 } 44 } 45 o[k] = 1; 46 for(j = 1; j <= n; j ++) 47 { 48 if(low[j] > min + p[k][j]&&o[j] == 0) 49 { 50 low[j] = min +p[k][j]; 51 } 52 } 53 } 54 printf("%d\n",low[n]); 55 } 56 return 0; 57 }
弗洛伊德O(n^3)
1 #include <stdio.h> 2 #include <string.h> 3 #define N 1000000 4 int p[101][101]; 5 int main() 6 { 7 int n,m,i,j,k,sv,ev,w; 8 while(scanf("%d%d",&n,&m)!=EOF) 9 { 10 if(n == 0&&m == 0) 11 break; 12 memset(p,0,sizeof(p)); 13 for(i = 0;i <= n;i ++) 14 for(j = 0;j <= n;j ++) 15 { 16 if(i == j) 17 p[i][j] = 0; 18 else 19 p[i][j] = N; 20 } 21 for(i = 1;i <= m;i ++) 22 { 23 scanf("%d%d%d",&sv,&ev,&w); 24 if(p[sv][ev] > w) 25 { 26 p[sv][ev] = w; 27 p[sv][ev] = w; 28 p[ev][sv] = w; 29 p[ev][sv] = w; 30 } 31 } 32 for(i = 1;i <= n;i ++) 33 for(j = 1;j <= n;j ++) 34 for(k = 1;k <= n;k ++) 35 { 36 if(p[j][k] > p[j][i] + p[i][k])//注意这个状态转移方程 37 p[j][k] = p[j][i] + p[i][k]; 38 } 39 printf("%d\n",p[1][n]); 40 } 41 return 0; 42 }