1.对于树中的任意一点,距离其最远的点一定是树的直径的某一端点
2.同一棵树的直径的中点相同(题目里给出来的,虽然不知道怎么用)
3.要求的一定在直径上,并且越长越好(不在直径上的点到端点的距离
≥
直径上的点到端点的距离,都取较大的那个)
4.任意搞一条直径求出来的偏心距是一样的
随意求一条直径,然后抠出来枚举头尾处理一下
当前的这条链到别的点中最长的距离为max(到两端点的距离,到不在直径的点的最远距离)
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 500000
using namespace std;
struct edge{int to,v,next;}e[N*2+5];
int n,S,cnt,L,R,ans,head[N+5],que[N+5],fa[N+5],dis[N+5],dir[N+5];
inline void add(int x,int y,int z){
e[++cnt]=(edge){y,z,head[x]};head[x]=cnt;
e[++cnt]=(edge){x,z,head[y]};head[y]=cnt;
}
inline void bfs(int x,int opt){
int h=0,t=1;
que[1]=x;memset(dis,-1,sizeof(dis));dis[x]=0;
while(h<=t){
++h;
int u=que[h];
for(int i=head[u];i;i=e[i].next)
if(dis[e[i].to]==-1){
dis[e[i].to]=dis[u]+e[i].v;
if(opt==1) fa[e[i].to]=u;
que[++t]=e[i].to;
}
}
}
void dfs(int x,int f){
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=f&&!dir[e[i].to]){
dis[e[i].to]=dis[x]+e[i].v;
dfs(e[i].to,x);
}
}
int main(){
scanf("%d%d",&n,&S);
for(int i=1,x,y,z;i<n;++i) {
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
L=1;bfs(L,0);for(int i=1;i<=n;++i) L=dis[i]>dis[L]?i:L;
R=L;bfs(L,1);for(int i=1;i<=n;++i) L=dis[i]>dis[L]?i:L;
for(int i=L;i;i=fa[i]) dir[i]=1;
ans=1<<30;
for(int p=L,q=L;p;p=fa[p]){
while(fa[q]&&dis[p]-dis[fa[q]]<=S) q=fa[q];
ans=min(ans,max(dis[q],dis[L]-dis[p]));
}
for(int i=L;i;i=fa[i])
dis[i]=0,dfs(i,fa[i]);
for(int i=1;i<=n;++i) ans=max(ans,dis[i]);
printf("%d\n",ans);
}