BZOJ 2599: [IOI2011]Race

点分治模板

#include<cstdio>
#include<algorithm>
using namespace std;
int cnt,n,K,ans,N,root,F_top,last[1000005],sz[1000005],F_[1000005],vis[1000005],F_stack[1000005],G_stack[1000005],F[1000005],G[1000005];
struct node{
	int to,next,val;
}e[1000005];
void add(int a,int b,int c){
	e[++cnt].to=b;
	e[cnt].next=last[a];
	e[cnt].val=c;
	last[a]=cnt;
}
void find_root(int x,int fa){
	sz[x]=1,F_[x]=0;
	for (int i=last[x]; i; i=e[i].next){
		int V=e[i].to;
		if (V==fa || vis[V]) continue;
		find_root(V,x);
		sz[x]+=sz[V];
		F_[x]=max(F_[x],sz[V]);
	}
	F_[x]=max(F_[x],N-sz[x]);
	if (F_[x]<F_[root]) root=x;
}
void get_dis(int x,int fa,int val,int dep){
	sz[x]=1;
	if (val==K) ans=min(ans,dep);
	if (val<=K) F_stack[++F_top]=val;
	if (val<=K) F[val]=min(F[val],dep);
	for (int i=last[x]; i; i=e[i].next){
		int V=e[i].to;
		if (vis[V] || V==fa) continue;
		get_dis(V,x,val+e[i].val,dep+1);
		sz[x]+=sz[V];
	}
}
void solve(int x){
	int G_top=0;
	for (int i=last[x]; i; i=e[i].next){
		int V=e[i].to;
		if (vis[V]) continue;
		F_top=0;
		get_dis(V,x,e[i].val,1);
		for (int j=1; j<=F_top; j++) ans=min(ans,F[F_stack[j]]+G[K-F_stack[j]]);
		for (int j=1; j<=F_top; j++) G[F_stack[j]]=min(G[F_stack[j]],F[F_stack[j]]),F[F_stack[j]]=1e9,G_stack[++G_top]=F_stack[j];
	}
	for (int i=1; i<=G_top; i++) G[G_stack[i]]=1e9;
}
void divide(int x){
	vis[x]=1;
	solve(x);
	for (int i=last[x]; i; i=e[i].next){
		int V=e[i].to;
		if (vis[V]) continue;
		N=sz[V],root=0;
		find_root(V,x);
		divide(root);
	}
}
int main(){
	scanf("%d%d",&n,&K);
	for (int i=1; i<n; i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		x++,y++;
		add(x,y,z);
		add(y,x,z);
	}
	for (int i=1; i<=K; i++) F[i]=G[i]=1e9;
	ans=1e9;
	N=n,root=0;
	F_[0]=1e9;
	find_root(1,0);
	divide(root);
	if (ans!=1e9) printf("%d\n",ans);
	else printf("-1\n");
	return 0;
}

  

posted @ 2018-10-13 19:55  ~Silent  阅读(145)  评论(0编辑  收藏  举报
Live2D