[BZOJ2599]Race

Assuming that the current divide and conquer to $x$, record $t_i$ as the minimum number of edges to $x$ among the points whose distance is $i$ to $x$, then we adopt divide and conquer 2: count one son and set each time The contribution generated by the midpoint, and the son information is merged into the set. Assuming that the current statistics to $u$, the number of edges from $u$ to $x$ is $d$, then use $d+t_{k-dis_{x ,u}}$ can update the answer, pay attention to traverse the subtree instead of the memset when resetting $t_i$ at the end, otherwise the complexity cannot be guaranteed

#include<stdio.h>
const int inf=100000000;
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
int h[200010],to[400010],nex[400010],w[400010],M;
void add(int a,int b,int c){
	M++;
	to[M]=b;
	w[M]=c;
	nex[M]=h[a];
	h[a]=M;
}
bool v[200010];
int siz [200010], n;
void dfs1(int fa,int x){
	n++;
	you [x] = 1;
	for(int i=h[x];i;i=nex[i]){
		if(!v[to[i]]&&to[i]!=fa){
			dfs1(x,to[i]);
			you [x] + = you [to [i]];
		}
	}
}
int mn,cn;
void dfs2(int fa,int x){
	int i,k;
	k=0;
	for(i=h[x];i;i=nex[i]){
		if(!v[to[i]]&&to[i]!=fa){
			dfs2(x,to[i]);
			k=max(k,siz[to[i]]);
		}
	}
	k = max (k, n-siz [x]);
	if(k<mn){
		mn = k;
		cn=x;
	}
}
int t[1000010],k,years;
void dfs3(int fa,int x,int dep,int dis){
	if(dis<=k)ans=min(ans,dep+t[k-dis]);
	for(int i=h[x];i;i=nex[i]){
		if(!v[to[i]]&&to[i]!=fa)dfs3(x,to[i],dep+1,dis+w[i]);
	}
}
void dfs4 (int fa, int x, int dep, int dis) {
	if(dis<=k)t[dis]=min(t[dis],dep);
	for(int i=h[x];i;i=nex[i]){
		if(!v[to[i]]&&to[i]!=fa)dfs4(x,to[i],dep+1,dis+w[i]);
	}
}
void dfs5(int fa,int x,int dis){
	if(dis<=k)t[dis]=inf;
	for(int i=h[x];i;i=nex[i]){
		if(!v[to[i]]&&to[i]!=fa)dfs5(x,to[i],dis+w[i]);
	}
}
void solve(int x){
	int i;
	n=0;
	dfs1(0,x);
	mn=inf;
	dfs2(0,x);
	x=cn;
	t[0]=0;
	for(i=h[x];i;i=nex[i]){
		if(!v[to[i]]){
			dfs3(x,to[i],1,w[i]);
			dfs4(x,to[i],1,w[i]);
		}
	}
	dfs5(0,x,0);
	v[x]=1;
	for(i=h[x];i;i=nex[i]){
		if(!v[to[i]])solve(to[i]);
	}
	
}
int main(){
	int n,i,a,b,c;
	scanf("%d%d",&n,&k);
	for(i=1;i<n;i++){
		scanf("%d%d%d",&a,&b,&c);
		a++;
		b++;
		add(a,b,c);
		add(b,a,c);
	}
	for(i=0;i<=k;i++)t[i]=inf;
	ans=inf;
	solve(1);
	if(ans==inf)ans=-1;
	printf("%d",ans);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325037792&siteId=291194637