Description
![](http://www.lydsy.com/JudgeOnline/images/1509.jpg)
Input
第一行是两个整数N(3 N 200000)和M,分别表示居住点总数和街道总数。以下M行,每行给出一条街道的信息。第i+1行包含整数Ui、Vi、Ti(1Ui, Vi N,1 Ti 1000000000),表示街道i连接居住点Ui和Vi,并且经过街道i需花费Ti分钟。街道信息不会重复给出。
Output
仅包含整数T,即最坏情况下Chris的父母需要花费T分钟才能找到Chris。
题解:
很明显是一道树的直径,肯定有两个点在树的直径的两端,在暴力找找第三个点在哪就好了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int N=200010;
struct node{
int x,y,next;
ll z;
}sa[N*2];int len=0,first[N];
int n,m;
void ins(int x,int y,ll z)
{
len++;
sa[len].x=x;
sa[len].y=y;
sa[len].z=z;
sa[len].next=first[x];
first[x]=len;
}
int fa[N],rt=1;
ll dis[N];
void dfs1(int x,int f)
{
fa[x]=f;
for(int i=first[x];i!=-1;i=sa[i].next)
{
int y=sa[i].y;
if(y!=f)
{
dis[y]=dis[x]+sa[i].z;
dfs1(y,x);
}
}
if(dis[x]>dis[rt]) rt=x;
}
int st,ed;
bool tf[N];
int maxtr[N],tot=0;
void mark()
{
int x=ed;
while(x!=fa[st])
{
tf[x]=1;
maxtr[++tot]=x;
x=fa[x];
}
}
ll maxx=0;
ll ddis[N];
void dfs2(int x,int f)
{
for(int i=first[x];i!=-1;i=sa[i].next)
{
int y=sa[i].y;
if(y!=f&&!tf[y])
{
ddis[y]=ddis[x]+sa[i].z;
dfs2(y,x);
}
}
maxx=max(ddis[x],maxx);
}
int main()
{
scanf("%d%d",&n,&m);
int x,y;ll z;
memset(first,-1,sizeof(first));
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&x,&y,&z);
ins(x,y,z);ins(y,x,z);
}
dfs1(1,0);st=rt;
memset(dis,0,sizeof(dis));dfs1(st,0);ed=rt;
mark();
//memset(dis,0,sizeof(dis));
ll ans=0;
for(int u=1;u<=tot;u++)
{
x=maxtr[u];
maxx=0;
dfs2(x,0);
ll yu=dis[ed]+min(dis[ed]-dis[x],dis[x])+maxx;
ans=max(ans,yu);
}
printf("%lld",ans);
}