Rase[点分治]

 


点分治,处理出每个点的dis与dep , 用ans[i]表示i可能作为答案

然后按dis排序,两个指针扫到dis=k的就更新ans[dep] , 处理子树的时候减一下子树的贡献就可以了

复杂度O(n*logn^2)


#include<bits/stdc++.h>
#define N 200005
#define inf 0x3fffffff
using namespace std;
int first[N],next[N*2],to[N*2],w[N*2],tot;
int n,k,vis[N],ans[N],dep[N],now;
int size[N],Siz,rt,Mson[N]; 
struct Node{int dis,dep;}tmp[N];
bool cmp(Node a,Node b){return a.dis<b.dis;}
void add(int x,int y,int z){
	next[++tot]=first[x],first[x]=tot,to[tot]=y,w[tot]=z;
}
void Get_rt(int u,int f){
	size[u]=1;
	for(int i=first[u];i;i=next[i]){
		int t=to[i]; if(t==f || vis[t]) continue;
		Get_rt(t,u); size[u]+=size[t];
		Mson[u]=max(Mson[u],size[t]);
	}
	Mson[u] = max(Mson[u],Siz-Mson[u]);
	if(Mson[u]<Mson[rt]) rt=u;
}
void dfs(int u,int f,int dis,int dep){
	tmp[++now].dis = dis; tmp[now].dep = dep;
	for(int i=first[u];i;i=next[i]){
		int t=to[i]; if(t==f || vis[t]) continue;
		dfs(t,u,dis+w[i],dep+1);
	}
}
void calc(int x,int d,int op){
	now=0 , dfs(x,0,d,0);
	sort(tmp+1,tmp+now+1,cmp);
	int i=1,j=now;
	while(i<j){
		int res = tmp[i].dis + tmp[j].dis;
		if(res==k){
			int Dep;
			if(op==-1) Dep=tmp[i].dep+tmp[j].dep+2;
			else Dep=tmp[i].dep+tmp[j].dep;
			ans[Dep] += op , i++;
		}
		else if(res<k) i++; else j--;
	}
}
void Solve(int x){
	calc(x,0,1); vis[x]=1;
	for(int i=first[x];i;i=next[i]){
		int t=to[i]; if(vis[t]) continue;
		calc(t,w[i],-1); 
		Siz=size[t] , rt=0 , Get_rt(t,0);
		Solve(rt);
	}
}
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);
		add(x+1,y+1,z),add(y+1,x+1,z); 
	}
	rt=0 , Mson[0]=inf , Siz=n , Get_rt(1,0);
	Solve(rt); for(int i=1;i<=n;i++) 
		if(ans[i]>0) {printf("%d",i); return 0;}
	printf("-1"); return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值