一道最短路的题
题目大意:有一堆多米诺骨牌,有n个关键点,有m条路,对于m条路,输入a,b,c表示从a推到b需要耗时间c。问从1号关键点开始推将所有多米诺骨牌都推倒需要耗费多长时间。
遍历一遍dis【i】,找到最长路设定为maxn,记录对应节点。
遍历所有边,在这条边中有这样三条信息:dis【u】,dis【v】,w【u,v】。我们知道,分别代表:从节点1最快速度推到节点u的时间,从节点1最快速度推到节点v的时间,以及u,v之间的时间,
①如果有这样的边存在,那么终点就不能能是一个节点,而是一条边中的某个地方。
②如果有这样的边存在,那么完成这一片区域的推倒时间为:(dis【u】+dis【v】+w【u,v】)/2 。
那么我们就来枚举每一条边,如果有这样的边存在了,那么就计算一次(dis【u】+dis【v】+w【u,v】)/2 。维护其最大值记做maxn2,并且记录这条边的两个节点。这时候如果maxn2>maxn。那么就输出其maxn2,和最大值对应的两个节点。相反的,输出maxn和那个单独节点。
注意输出格式
贴代码:
dijkstra无优化
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 505
#define inf 0x3f3f3f3f
using namespace std;
int n,m,cnt,head[maxn],t,num,dis[maxn];
double mx;
bool used[maxn];
struct Node{
int to,nxt;
int tim;
}edge[maxn*10];
void add(int x,int y,int z)
{
cnt++;
edge[cnt].to=y;
edge[cnt].nxt=head[x];
edge[cnt].tim=z;
head[x]=cnt;
}
void dijkstra(int s)
{
for(int i=1;i<=n;i++)
{
dis[i]=inf;
used[i]=0;
}
dis[s]=0;
for(int k=1;k<=n;k++)
{
int minn=inf,tar;
for(int i=1;i<=n;i++)
{
if(!used[i] && dis[i]<minn) minn=dis[i],tar=i;
}
used[tar]=1;
for(int i=head[tar];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(!used[v] && dis[v]>dis[tar]+edge[i].tim)
{
dis[v]=dis[tar]+edge[i].tim;
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0 && m==0) break;
num++;
cnt=0;
memset(head,0,sizeof head);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z); add(y,x,z);
}
printf("System #%d\n",num);
if(n==1)
{
printf("The last domino falls after 0.0 seconds, at key domino 1.\n\n");
continue;
}
dijkstra(1);
mx=t=0;
for(int i=1;i<=n;i++)
{
if(mx<dis[i]) mx=dis[i]*1.0,t=i;
}
int ta,tb;
double mx2=0;
for(int i=1;i<=n;i++)
{
for(int j=head[i];j;j=edge[j].nxt)
{
int v=edge[j].to;
double tmp=(dis[i]+dis[v]+edge[j].tim)/2.0;
if(tmp>mx2)
{
mx2=tmp;
ta=i,tb=v;
}
}
}
if(mx2>mx)
{
printf("The last domino falls after %.1lf seconds, between key dominoes %d and %d.\n\n",mx2,ta,tb);
}
else
printf("The last domino falls after %.1lf seconds, at key domino %d.\n\n",mx,t);
}
return 0;
}