题目链接:
https://vjudge.net/problem/POJ-1135
题目大意:
有N个关键的多米诺骨牌,这些牌通过一些路径相连接,这些路径是由一排其他骨牌构成的。已知每一条路径上的骨牌倒下需要的时间。现在从把编号为1的关键骨牌推倒,问多长时间后所有的骨牌(包括关键牌和它们之间的路径上的骨牌)都倒下,时间精确到小数点后一位。
思路:
先用dijkstra算法计算每一张骨牌倒下的时间d[i],然后取最大值time1。
再每两张骨牌之间全部倒下的时间的最大值time2 = max{(d[i] + d[j] + Map[i][j]) / 2}
如果time1>=time2,那就是在某张关键牌处结束,不然则在两张关键牌中结束
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<map> 9 #include<sstream> 10 using namespace std; 11 typedef long long ll; 12 const int maxn = 500 + 10; 13 const int INF = 1 << 30; 14 int T, n, m, cases; 15 int Map[maxn][maxn]; 16 bool v[maxn]; 17 int d[maxn]; 18 void dijkstra(int u0) 19 { 20 memset(v, 0, sizeof(v)); 21 for(int i = 1; i <= n; i++)d[i] = (i == u0 ? 0 : INF); 22 for(int i = 1; i <= n; i++) 23 { 24 int x, m = INF; 25 for(int j = 1; j <= n; j++)if(!v[j] && d[j] <= m)m = d[x = j]; 26 v[x] = 1; 27 for(int j = 1; j <= n; j++) 28 d[j] = min(d[j], d[x] + Map[x][j]);//松弛操作 29 } 30 } 31 int main() 32 { 33 while(cin >> n >> m) 34 { 35 if(!n && !m)break; 36 for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++)Map[i][j] = INF; 37 int x, y, z; 38 for(int i = 0; i < m; i++) 39 { 40 cin >> x >> y >> z; 41 Map[x][y] = Map[y][x] = z; 42 } 43 dijkstra(1); 44 double mintime1 = -INF, mintime2 = -INF; 45 int ans, ans1, ans2; 46 for(int i = 1; i <= n; i++) 47 { 48 if(mintime1 < d[i]) 49 { 50 mintime1 = d[i]; 51 ans = i; 52 } 53 } 54 for(int i = 1; i <= n; i++) 55 { 56 for(int j = 1; j <= n; j++) 57 { 58 if(Map[i][j] == INF)continue; 59 if(mintime2 < 1.0 * (d[i] + d[j] + Map[i][j]) / 2.0) 60 { 61 mintime2 = 1.0 * (d[i] + d[j] + Map[i][j]) / 2.0; 62 ans1 = i, ans2 = j; 63 } 64 } 65 } 66 printf("System #%d\n", ++cases); 67 if(mintime1 >= mintime2)printf("The last domino falls after %.1f seconds, at key domino %d.\n\n", mintime1, ans); 68 else printf("The last domino falls after %.1f seconds, between key dominoes %d and %d.\n\n", mintime2, ans1, ans2); 69 } 70 }