POJ 1135 Domino Effect(最短路径)
题意
有m排放置好的多米诺骨牌,每排的头尾骨牌称为“关键骨牌”,共有n个关键骨牌,每排多米诺倒下需要L秒,关键骨牌倒下的时间忽略不计。推倒关键骨牌1,求最后一个骨牌倒下的时间及位置。(若最后一个倒下的骨牌不是关键骨牌,则按升序输出这个骨牌所在的那一排的两端的关键骨牌)
样例输入
2 1
1 2 27
3 3
1 2 5
1 3 5
2 3 5
0 0
样例输出
System #1
The last domino falls after 27.0 seconds, at key domino 2.
System #2
The last domino falls after 7.5 seconds, between key dominoes 2 and 3.
思路
无向图,先用dijkstra算法求出从关键骨牌1到各个关键骨牌的最短路径(即最短耗时)。而与最短路径不相干的边倒下的时刻,则是关键骨牌1到这条边两端的关键骨牌所需的最短时间之和,再加上这条边倒下所需的时间,再除以2。(理解这一点是这道题的关键,类似与相遇问题)最后,只要比较关键骨牌1到某个关键骨牌的最短路径耗时 和 某条边的倒下的时刻,取两者中较大的一方,即可得出结论。
注意点
由于关键骨牌倒下时间忽略不计,所以当输入数据只有1个骨牌时,耗时为0.0,倒下的关键骨牌为1本身。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <string.h> 4 #include <queue> 5 using namespace std; 6 7 const int N = 510, INF = 0x3f3f3f3f; 8 int graph[N][N]; 9 10 void SPFA(int n) 11 { 12 queue<int> q; 13 bool vis[N] = {0}; 14 vis[0] = true; 15 int D[N]; 16 for(int i=0; i<n; ++i) 17 { 18 D[i] = graph[0][i]; 19 if(graph[0][i] != INF) 20 { 21 q.push(i); 22 vis[i] = true; 23 } 24 } 25 while(!q.empty()) 26 { 27 int x = q.front(); 28 for(int i=0; i<n; ++i) 29 { 30 int dis = D[x] + graph[x][i]; 31 if(dis < D[i]) 32 { 33 D[i] = dis; 34 if(!vis[i]) 35 { 36 q.push(i); 37 vis[i] = true; 38 } 39 } 40 } 41 q.pop(); 42 vis[x] = false; 43 } 44 D[0] = 0; 45 int Max1 = 0, Max2 = 0, sum, tag1, tag21, tag22; 46 for(int i=1; i<n; ++i) 47 if(D[i] > Max1) 48 Max1 = D[i], tag1 = i; 49 for(int i=0; i<n; ++i) 50 { 51 for(int j=i+1; j<n; ++j) 52 { 53 if(graph[i][j] != INF) 54 sum = D[i] + D[j] + graph[i][j]; 55 if(sum > Max2) 56 Max2 = sum, tag21 = i, tag22 = j; 57 } 58 } 59 double ans = (double)Max2 / 2; 60 if(ans <= (double)Max1) 61 printf("The last domino falls after %.1lf seconds, at key domino %d.\n\n", (double)Max1, tag1+1); 62 else 63 printf("The last domino falls after %.1lf seconds, between key dominoes %d and %d.\n\n", ans, tag21+1, tag22+1); 64 return ; 65 } 66 67 int main(void) 68 { 69 int n, m, u, v, w; 70 for(int t=0; scanf("%d %d", &n, &m), n+m; ) 71 { 72 memset(graph, INF, sizeof(graph)); 73 for(int i=0; i<m; ++i) 74 { 75 scanf("%d %d %d", &u, &v, &w); 76 --u, --v; 77 graph[u][v] = w; 78 graph[v][u] = w; 79 } 80 printf("System #%d\n", ++t); 81 if(n == 1) 82 printf("The last domino falls after 0.0 seconds, at key domino 1.\n\n"); 83 else 84 SPFA(n); 85 } 86 return 0; 87 }
测试数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
2 1 1 2 27 3 3 1 2 5 1 3 5 2 3 5 1 0 5 7 1 2 1 1 3 2 1 4 3 1 5 5 2 3 1 3 4 1 4 5 1 4 5 1 2 3 1 3 3 1 4 5 3 4 2 2 3 9 3 3 1 3 1 1 2 3 2 3 3 0 0
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
System #1 The last domino falls after 27.0 seconds, at key domino 2. System #2 The last domino falls after 7.5 seconds, between key dominoes 2 and 3. System #3 The last domino falls after 0.0 seconds, at key domino 1. System #4 The last domino falls after 4.5 seconds, between key dominoes 1 and 5. System #5 The last domino falls after 7.5 seconds, between key dominoes 2 and 3. System #6 The last domino falls after 3.5 seconds, between key dominoes 2 and 3.