POJ1135 Domino Effect(SPFA)

题目大概是,普通骨牌连接两张关键骨牌,一旦一张关键骨牌倒下与其相邻的普通骨牌也倒下,普通骨牌倒下与其相邻的骨牌也倒下。给出所有有普通骨牌相连的两个关键骨牌之间普通骨牌倒下所需时间,问1号关键骨牌开始倒下后最后一张骨牌倒下的时间和位置。

居然是最短路。。记dist[u]为起点骨牌1到关键骨牌u的最短时间,跑个单源最短路可得出。最后倒下的骨牌,有两种情况:

  1. 倒下的是关键骨牌u,那么倒下的时间就是dist[u]
  2. 倒下的是关键骨牌u和v之间某张普通骨牌,那么倒下的时间就是 (dist[u]+dist[v]+time(u,v))/2,因为:
    • dist[u]=dist[v]显然成立,不等于的情况不妨设dist[u]<dist[v];
    • 那么过了dist[u]的时间后,通往u点的骨牌到正好达u点,而通往v点的还需dist[v]-dist[u]的时间到达v;
    • 因而两边这时还有dist[v]-dist[u]+time(u,v)的时间长度,两边同时倒就还需要(dist[v]-dist[u]+time(u,v))/2的时间;
    • 所以总共需要(dist[v]-dist[u]+time(u,v))/2+dist[u],即(dist[v]+dist[u]+time(u,v))/2的时间。

这样分别搞搞这两种情况,就能找到答案。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #include<algorithm>
 5 using namespace std;
 6 #define MAXN 555
 7 #define MAXM 555*555*2
 8 
 9 struct Edge{
10     int u,v,cost,next;
11 }edge[MAXM];
12 int head[MAXN],NE,n;
13 void addEdge(int a,int b,int c){
14     edge[NE].u=a; edge[NE].v=b; edge[NE].cost=c; edge[NE].next=head[a];
15     head[a]=NE++;
16 }
17 
18 int d[MAXN];
19 void SPFA(int vs){
20     memset(d,127,sizeof(d));
21     d[vs]=0;
22     bool vis[MAXN]={0};
23     vis[vs]=1;
24     queue<int> que;
25     que.push(vs);
26     while(!que.empty()){
27         int u=que.front(); que.pop();
28         for(int i=head[u]; i!=-1; i=edge[i].next){
29             int v=edge[i].v;
30             if(d[v]>d[u]+edge[i].cost){
31                 d[v]=d[u]+edge[i].cost;
32                 if(!vis[v]){
33                     vis[v]=1;
34                     que.push(v);
35                 }
36             }
37         }
38         vis[u]=0;
39     }
40 }
41 int main(){
42     int m,a,b,c,cse=0;
43     while(~scanf("%d%d",&n,&m) && (n||m)){
44         NE=0;
45         memset(head,-1,sizeof(head));
46         while(m--){
47             scanf("%d%d%d",&a,&b,&c);
48             addEdge(a,b,c);
49             addEdge(b,a,c);
50         }
51         SPFA(1);
52         double res=-1;
53         bool flag=0;
54         for(int i=1; i<=n; ++i){
55             if(d[i]>res){
56                 res=d[i];
57                 a=i;
58             }
59         }
60         for(int i=0; i<NE; i+=2){
61             double tmp=(d[edge[i].u]+d[edge[i].v]+edge[i].cost)/2.0;
62             if(tmp>res){
63                 res=tmp;
64                 flag=1;
65                 a=edge[i].u; b=edge[i].v;
66                 if(a>b) swap(a,b);
67             }
68         }
69         printf("System #%d\n",++cse);
70         if(flag) printf("The last domino falls after %.1f seconds, between key dominoes %d and %d.\n\n",res,a,b);
71         else printf("The last domino falls after %.1f seconds, at key domino %d.\n\n",res,a);
72     }
73     return 0;
74 }

 

你可能感兴趣的:(POJ1135 Domino Effect(SPFA))