不错的最短路径题目。
/* *State: POJ1135 Accepted 1204K 0MS C++ 1854B *题目大意: * 有一个多米诺骨牌的游戏,我们知道有关键骨牌和普通骨牌,将 * 关键骨牌推倒之后,整个骨牌阵就会倒下,推动其他的关键骨牌, * 其中推倒关键骨牌A使的关键骨牌B也倒,需要一定的时间,所以 * 本题要求求出最后一个倒的骨牌的位置,及其时间 *解题思路: * 想一下结果,其实最后一个骨牌倒的位置只有2种情况,要么就是 * 在关键骨牌的位置,要么就是在两个关键骨牌之间。之后就好做了, * 如果倒在关键骨牌,那么只要计算各个关键骨牌的最短路即可。如果 * 倒在两个关键骨牌之间,那么就是两个关键骨牌的最短路的和+两个 * 关键骨牌的距离再除以2. *解题感想: * 感觉这一道题真的出得挺好的,一开始还想到用搜索呢,但是其实 * 如果考虑到了该问题的本质,由骨牌的最终状态考虑回来,那么就 * 可以想到用最短路了。 */
View Code
#include <iostream> #include <queue> #include <vector> using namespace std; const int MAXN = 505; const int inf = 0x3f3f3f3f; int Map[MAXN][MAXN]; vector<int> ind; double Max; void init() { ind.clear(); Max = -1; for(int i = 0; i < MAXN; i++) for(int j = 0; j < MAXN; j++) Map[i][j] = inf; } int spfa(int s, int n) { int inQ[MAXN] = {0}; int dis[MAXN]; for(int i = 0; i <= n; i++) dis[i] = inf; queue<int> Q; Q.push(s); inQ[s] = 1; dis[s] = 0; while(!Q.empty()) { int pre = Q.front(); inQ[pre] = 0; Q.pop(); for(int i = 1; i <= n; i++) { int w = Map[pre][i]; if(Map[pre][i] != inf && dis[i] > dis[pre] + w) { dis[i] = dis[pre] + w; if(!inQ[i]) { Q.push(i); inQ[i] = 1; } } } } for(int i = 1; i <= n; i++) { if(dis[i] > Max) { Max = dis[i]; ind.clear(); ind.push_back(i); } } for(int i = 1; i <= n; i++) for(int j = i + 1; j <= n; j++) { if(Map[i][j] != inf) { double t = (dis[i] + dis[j] + Map[i][j]) / 2.0; if(t > Max) { Max = t; ind.clear(); ind.push_back(i); ind.push_back(j); } } } return 0; } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, m, cas_c = 1; while(scanf("%d %d",&n, &m), n || m) { int u, v, w; init(); for(int i = 0; i < m; i++) { scanf("%d %d %d", &u, &v, &w); Map[u][v] = Map[v][u] = w; } spfa(1, n); printf("System #%d\n", cas_c++); if(ind.size() == 1) printf("The last domino falls after %.1lf seconds, at key domino %d.\n", Max, ind[0]); else if(ind.size() == 2) printf("The last domino falls after %.1lf seconds, between key dominoes %d and %d.\n", Max, ind[0], ind[1]); printf("\n"); } return 0; }