首先看题解,看到的是floyd,然后就往floyd方向去想,想不咋通,之后就问了队长,队长解释了一下就清楚了
这一题用的是floyd和二分的思想,如果只是floyd的思想就是求任意两点之间距离为k(1<=k<=N)条边的最短距离,然后在此基础上求k+1条边的最短距离……
1 #include <cstdio> 2 #include <cstring> 3 4 const int maxlen = 1000+10; 5 int N,T,S,E; 6 int map[maxlen][maxlen]; 7 int sign[maxlen]; 8 int tmp[maxlen][maxlen]; 9 bool used[maxlen]; 10 int ans[maxlen][maxlen]; 11 int cnt; 12 13 void floyd(int a[][maxlen],int b[][maxlen]) 14 { 15 //memset(tmp,-1,sizeof(tmp)); 16 for(int k = 0;k < cnt;k ++) 17 { 18 for(int i = 0;i < cnt;i ++) 19 { 20 if(a[sign[i]][sign[k]] != -1) 21 { 22 for(int j = 0;j < cnt;j ++) 23 { 24 if(b[sign[k]][sign[j]] != -1) 25 { 26 if(tmp[sign[i]][sign[j]] == -1 || tmp[sign[i]][sign[j]] > b[sign[k]][sign[j]] + a[sign[i]][sign[k]]) 27 { 28 tmp[sign[i]][sign[j]] = a[sign[i]][sign[k]] + b[sign[k]][sign[j]]; 29 } 30 } 31 } 32 } 33 } 34 } 35 36 for(int i = 0;i < cnt;i ++) 37 { 38 for(int j = 0;j < cnt;j ++) 39 { 40 a[sign[i]][sign[j]] = tmp[sign[i]][sign[j]]; 41 tmp[sign[i]][sign[j]] = -1; 42 } 43 } 44 //memcpy(a,tmp,sizeof(tmp));这里用这个就会超时,/可怜 45 } 46 47 void solve(int k) 48 { 49 memset(ans,-1,sizeof(ans)); 50 memset(tmp,-1,sizeof(tmp)); 51 for(int i = 0;i < maxlen;i ++) 52 { 53 ans[i][i] = 0; 54 } 55 while(k) 56 { 57 if(k%2) 58 { 59 floyd( ans,map); 60 } 61 floyd(map,map); 62 k = k >> 1; 63 } 64 } 65 66 int main() 67 { 68 while(scanf("%d%d%d%d",&N,&T,&S,&E) == 4) 69 { 70 memset(map,-1,sizeof(map)); 71 memset(used,false,sizeof(used)); 72 cnt = 0; 73 for(int i = 0;i < T;i ++) 74 { 75 int p,s,t; 76 scanf("%d%d%d",&p,&s,&t); 77 if(map[s][t] == -1 || map[s][t] > p) 78 { 79 map[s][t] = p; 80 map[t][s] = p; 81 } 82 if(!used[s]) 83 { 84 used[s] = true; 85 sign[cnt ++] = s; 86 } 87 if(!used[t]) 88 { 89 used[t] = true; 90 sign[cnt ++] = t; 91 } 92 } 93 solve(N); 94 printf("%d\n",ans[S][E]); 95 } 96 return 0; 97 }