题目链接:http://poj.org/problem?id=1135
题目大意:有n个多米诺关键牌(1~n)标号,之间有m排多米诺非关键牌相连,要求出把1号关键牌推倒后,最后倒下的关键牌的位置和倒下的时间。
解题思路:
有两种情况:
第一是倒下的最后一张牌刚好是关键牌,第二是倒下的最后一张牌是非关键牌。
以关键牌为顶点,求出1号牌到其他各个牌之间的最短路径(也就是时间);
接下来先求出1号牌到其他各个关键牌之间的最短路径中的最大路径,时间为Max1;
计算关键牌两两之间所有牌完全倒下的时间,时间为Max2;
比较Max1和Max2,若Max1>=Max2,就是第一种情况,反之为第二种;
#include<iostream>
using namespace std;
const int Max_time=1<<26;
int path[505][505];
int time[505];
int visit[505];
int m,n;
void Dijkstra()
{
memset(visit,0,sizeof(visit));
/*Initial*/
for(int i=1;i<=n;i++)
time[i]=path[1][i];
time[1]=0;
int index,Min_time,num=1;
while(num++<=n)
{
index=0;
Min_time=Max_time;
for(int i=1;i<=n;i++)
{
if(!visit[i]&&time[i]<Min_time)
{
index=i;
Min_time=time[i];
}
}
visit[index]=1;
for(int j=1;j<=n;j++)
{
if(!visit[j]&&time[j]>time[index]+path[index][j])
time[j]=time[index]+path[index][j];
}
}
return ;
}
int main()
{
int i,j,cases=1;
for(;;)
{
scanf("%d %d",&n,&m);
{
if(!n&&!m) break;
if(cases!=1)
printf("\n");
/*Input*/
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
path[i][j]=Max_time;
}
for(i=1;i<=m;i++)
{
int start,end,cost;
scanf("%d %d %d",&start,&end,&cost);
path[start][end]=path[end][start]=cost;
}
}
/*Dijkstra*/
Dijkstra();
/*for(int x=1;x<=n;x++)
cout<<time[x]<<' ';
cout<<endl;*/
/*求最后倒下的关键牌的时间和位置*/
double Time1=-1;
int position;
for(i=1;i<=n;i++)
{
if(time[i]>Time1)
{
Time1=time[i];
position=i;
}
}
/*求最后倒下的为非关键牌的时间和位置*/
double temp,Time2=-1;
int position1,position2;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
temp=(time[i]+time[j]+path[i][j])/2.0;
if(path[i][j]<Max_time&&Time2<temp)
{
Time2=temp;
position1=i;
position2=j;
}
}
}
printf("System #%d\n",cases++);
printf("The last domino falls after ");
if(Time1>=Time2)
printf("%.1lf seconds, at key domino %d.\n",Time1,position);
else
printf("%.1lf seconds, between key dominoes %d and %d.\n",Time2,position1,position2);
}
return 0;
}