解题思路:用dijkstra求出最短路径,找到其中的最大值ans,那些走过的边上的牌不用考虑,肯定比ans小,再枚举没有走过的边,最后倒下的是dist[a]+dist[b]+d/2。注意点,当n==1时,ans为0,我在这里wa了五六次吧 #include<iostream> #include<cstdio> #include<queue> #include<cstdlib> #include<cstring> using namespace std; #define N 505 #define inf 100000000 int dist[N],pi[N]; bool use[N],ve[N][N]; struct node { int v,dist; }; struct cmp{ bool operator()(node a,node b){ return a.dist>b.dist; } }; priority_queue<node,vector<node>,cmp>que; struct edge { int v,dist; edge *next; }; edge *g[N]; struct storage { int a,b,d; }; storage s[N*N]; void add_edge(int u,int v,int d) { edge *ptr=new edge; ptr->dist=d; ptr->v=v; ptr->next=g[u]; g[u]=ptr; return ; } void dijkstra(int s,int n) { int i,u,v,w; node temp; for(i=1;i<=n;i++) dist[i]=inf; dist[s]=0; memset(use,0,sizeof(use)); temp.dist=0,temp.v=s; while(!que.empty()) que.pop(); que.push(temp); while(!que.empty()) { temp=que.top(); que.pop(); u=temp.v; if(use[u]) continue; use[u]=1; for(edge *ptr=g[u];ptr;ptr=ptr->next) { v=ptr->v,w=ptr->dist; if(dist[v]>dist[u]+w) { dist[v]=dist[u]+w; pi[v]=u; temp.dist=dist[v]; temp.v=v; que.push(temp); } } } } int main() { int n,m,a,b,d,i,left,right,ca=0; bool flag; double ans; while(scanf("%d%d",&n,&m)) { ca++; if(n==0&&m==0) break; for(i=1;i<=n;i++) g[i]=NULL; for(i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&d); s[i].a=a,s[i].b=b,s[i].d=d; add_edge(a,b,d); add_edge(b,a,d); } dijkstra(1,n); ans=0,flag=true; for(i=2;i<=n;i++) if(dist[i]>ans) { ans=dist[i]; left=i; } memset(ve,0,sizeof(ve)); for(i=2;i<=n;i++) ve[i][pi[i]]=ve[pi[i]][i]=1; for(i=1;i<=m;i++) { a=s[i].a,b=s[i].b,d=s[i].d; if(ve[a][b]) continue; if((dist[a]+dist[b]+d)/2.0>ans) { ans=(dist[a]+dist[b]+d)/2.0; flag=false; left=a,right=b; } } if(n==1) { ans=0; left=1; } printf("System #%d/n",ca); if(flag) printf("The last domino falls after %.1lf seconds, at key domino %d./n/n",ans,left); else printf("The last domino falls after %.1lf seconds, between key dominoes %d and %d./n/n",ans,left,right); } return 0; }