树网的核

树网的核
根据直径的性质,我们对任意直径计算是等同的,故只要求出一条直径就行了
然后我们将直径上的点标记,为\(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\n",ans);
	return 0;
}
/*
5 2
1 2 5
2 3 2
2 4 4
2 5 3

ans=5;
*/
posted @ 2020-07-25 18:54  行zzz  阅读(93)  评论(0编辑  收藏  举报