题目描述
Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:“喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?”一听说要考试,Chris的父母就心急如焚,他们决定在尽量短的时间内找到Chris。他们告诉Chris的老师:“根据以往的经验,Chris现在必然躲在朋友Shermie或Yashiro家里偷玩《拳皇》游戏。现在,我们就从家出发去找Chris,一但找到,我们立刻给您打电话。”说完砰的一声把电话挂了。
Chris居住的城市由N个居住点和若干条连接居住点的双向街道组成,经过街道x需花费Tx分钟。可以保证,任两个居住点间有且仅有一条通路。Chris家在点C,Shermie和Yashiro分别住在点A和点B。Chris的老师和Chris的父母都有城市地图,但Chris的父母知道点A、B、C的具体位置而Chris的老师不知。
为了尽快找到Chris,Chris的父母会遵守以下两条规则:
- 如果A距离C比B距离C近,那么Chris的父母先去Shermie家寻找Chris,如果找不到,Chris的父母再去Yashiro家;反之亦然。
- Chris的父母总沿着两点间唯一的通路行走。
显然,Chris的老师知道Chris的父母在寻找Chris的过程中会遵守以上两条规则,但由于他并不知道A,B,C的具体位置,所以现在他希望你告诉他,最坏情况下Chris的父母要耗费多长时间才能找到Chris?
输入格式
输入文件第一行是两个整数N(3 ≤ N ≤ 200000)和M,分别表示居住点总数和街道总数。
以下M行,每行给出一条街道的信息。第i+1行包含整数Ui、Vi、Ti(1≤Ui, Vi ≤ N,1 ≤ Ti ≤ 1000000000),表示街道i连接居住点Ui和Vi,并且经过街道i需花费Ti分钟。街道信息不会重复给出。
输出格式
输出文件仅包含整数T,即最坏情况下Chris的父母需要花费T分钟才能找到Chris。
输入输出样例
输入 #1
4 3 1 2 1 2 3 1 3 4 1
输出 #1
4
吐槽一下:题目这么长一大串,讲了一个故事,但其实用简洁的语言来说人话:在一个无根树中,有三个点ABC,求AB+BC(假设AB<AC)的最大值
———————————————————————————————————————————————————————————————
那不就是先求树的直径吗(直径:在一个树中相距最远的两个点之间的长度),设B,C点为直径的两个端点,那么A点在这条直径上
如图所示:四个点,三条边
那么很容易得出直径为3 端点为1 4
设这两个点为B C
2 3分别设为A1,A2
分类讨论:
1.当点A存在于A1时
那么顺序为A1——>B——>A1——>A2——>C
总长度为7
2.当点A存在于A2时
顺序为A2——>C——>A2——>A1——>B
总长度为9
显然第二种情况好一些
因此可以推出(d[j][i]表示i,j之间的最短距离):
ans=max(min(d[Ai][B],d[Ai][C])+d[B][C]
Ai表示存在于以BC为端点的直径上的所有点
一次搜索求直径端点,两次搜索枚举中间的点
上代码:
#include<bits/stdc++.h> using namespace std; const long long N=200002; long long number,m,ver[N],next[N],head[N],tot,edge[N],res[N],ans=0; long long q[N],hd,tl,dis[N],maxx=-1,maxi=0,start,begin,d1[N],d2[N]; long long read(){ long long s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar(); return s*w; } void add(long long x,long long y,long long z){ tot++;ver[tot]=y; edge[tot]=z;next[tot]=head[x]; head[x]=tot; } void bfs(long long x){ memset(res,0,sizeof(res));memset(dis,0,sizeof(dis)); hd=0;tl=1;q[1]=x;res[x]=1; while(hd^tl){ hd++; for(long long i=head[q[hd]];i;i=next[i]){ long long y=ver[i]; if(!res[y]){ res[y]=1;tl++;q[tl]=y; dis[y]=dis[q[hd]]+edge[i]; } } } for(long long i=1;i<=number;i++){ if(dis[i]>=maxx)maxx=dis[i],maxi=i; } } void dfs1(long long x,long long pd){ for(long long i=head[x];i;i=next[i]){ long long y=ver[i]; if(y==pd)continue; d1[y]=d1[x]+edge[i]; dfs1(y,x); } } void dfs2(long long x,long long pd){ for(long long i=head[x];i;i=next[i]){ long long y=ver[i]; if(y==pd)continue; d2[y]=d2[x]+edge[i]; dfs2(y,x); } } int main(){ number=read();m=read(); for(long long i=1;i<=m;i++){ long long x=read(),y=read(),z=read(); add(x,y,z);add(y,x,z); } bfs(1); start=maxi;bfs(maxi); begin=maxi; dfs1(start,0);dfs2(begin,0); for(long long i=1;i<=number;i++)ans=max(ans,min(d1[i],d2[i])); cout<<ans+maxx; return 0; }