点分治,处理出每个点的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;
}