树网的核
根据直径的性质,我们对任意直径计算是等同的,故只要求出一条直径就行了
然后我们将直径上的点标记,为(u_1,u_2,...,u_t)
设(d(u_x))为直径上一点(u_x)不通过直径上的边能到达的最远距离
我们枚举在直径上距离不超过s的区间((u_i,u_j)),考虑(ans=max(max_{i leq k leq j}{d(u_k)},dist(u_1,u_i),dist(u_j,u_t)))
又根据直径的最长性,等价于(ans=max(max_{1 leq k leq t}{d(u_k)},dist(u_1,u_i),dist(u_j,u_t)))
(maxd=max_{1 leq k leq t}{d(u_k)})是定值,用two-pointer枚举i,j,(O(N))解决
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)x.size())
#define ALL(x) x.begin(),x.end()
#define U(i,u) for(register int i=head[u];i;i=nxt[i])
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define per(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned int ui;
typedef pair<int,int> PII;
typedef vector<int> VI;
template<class T> inline void read(T &x){
x=0;char c=getchar();int f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f;
}
template<class T> inline void cmin(T &x, T y){x=x<y?x:y;}
template<class T> inline void cmax(T &x, T y){x=x>y?x:y;}
const int N=501;
int n,s,g[N][N],head[N],nxt[N<<1],v[N<<1],w[N<<1],cnt,mx,p,q,vis[N],d[N];
int ss[N],tt[N],maxd;
void add(int x,int y,int z){nxt[++cnt]=head[x];head[x]=cnt;v[cnt]=y;w[cnt]=z;}
void dfs1(int now,int fa,int di){
if(di>mx)mx=di,p=now;
U(i,now){
if(v[i]==fa)continue;
dfs1(v[i],now,di+w[i]);
}
}
int stak[N],sp;
void dfs2(int now,int fa){
if(now==q){
stak[++sp]=now;
return;
}U(i,now){
if(v[i]==fa)continue;
dfs2(v[i],now);
if(vis[v[i]]){vis[now]=1;stak[++sp]=now;return;}
}
}
void dfs3(int now,int fa,int di){
cmax(mx,di);U(i,now){
if(v[i]==fa)continue;
if(vis[v[i]])continue;
dfs3(v[i],now,di+w[i]);
}
}
int main(){
read(n);read(s);rep(i,1,n-1){int x,y,z;read(x);read(y);read(z);add(x,y,z);add(y,x,z);g[x][y]=g[y][x]=z;}
mx=0;dfs1(1,0,0);mx=0;q=p;dfs1(p,0,0);
vis[p]=vis[q]=1;dfs2(p,0);
rep(i,1,sp){mx=0;dfs3(stak[i],0,0);d[stak[i]]=mx;cmax(maxd,d[stak[i]]);}
rep(i,2,sp)ss[i]=ss[i-1]+g[stak[i-1]][stak[i]];per(i,sp-1,1)tt[i]=tt[i+1]+g[stak[i+1]][stak[i]];
int ans=0x3f3f3f3f;
rep(i,1,sp){
int j=i;
while(ss[j]-ss[i]<=s&&j<=sp){
int tmp=max(maxd,max(ss[i],tt[j]));
cmin(ans,tmp);
++j;
}
}
printf("%d
",ans);
return 0;
}
/*
5 2
1 2 5
2 3 2
2 4 4
2 5 3
ans=5;
*/