点分治
1、求树的重心
2、计算以当前重心为根的子树的答案
3、去掉以当前重心儿子为根的子树的答案
4、枚举每个儿子,分治
考虑计算过程如何实现
我们不妨记一个ans数组,ans[i]表示使用i条边权值为k的有多少对
每次实现2的时候,权值设为+1
每次实现3的时候,权值设为-1
1、求树的重心
2、计算以当前重心为根的子树的答案
3、去掉以当前重心儿子为根的子树的答案
4、枚举每个儿子,分治
考虑计算过程如何实现
我们不妨记一个ans数组,ans[i]表示使用i条边权值为k的有多少对
每次实现2的时候,权值设为+1
每次实现3的时候,权值设为-1
把子树内所有的dis排序,计算有多少对权值和为k的,两个指针扫一遍就可以了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 200100
using namespace std;
struct yts
{
int d1,d2;
}st[maxn];
int head[maxn],to[2*maxn],next[2*maxn],len[2*maxn],dis[maxn],dep[maxn];
int size[maxn],ans[maxn],fa[maxn];
bool vis[maxn];
int n,m,num,k,top;
bool cmp(yts x,yts y)
{
return x.d1<y.d1;
}
void addedge(int x,int y,int z)
{
num++;to[num]=y;len[num]=z;next[num]=head[x];head[x]=num;
}
void get_root(int x,int Size,int &cg)
{
bool flag=1;
size[x]=1;
for (int p=head[x];p;p=next[p])
if (!vis[to[p]] && to[p]!=fa[x])
{
fa[to[p]]=x;
get_root(to[p],Size,cg);
size[x]+=size[to[p]];
if (size[to[p]]>Size/2) flag=0;
}
if (Size-size[x]>Size/2) flag=0;
if (flag) cg=x;
}
void dfs1(int x,int d1,int d2)
{
dis[x]=d1;dep[x]=d2;
for (int p=head[x];p;p=next[p])
if (!vis[to[p]] && to[p]!=fa[x]) fa[to[p]]=x,dfs1(to[p],d1+len[p],d2+1);
}
void dfs2(int x)
{
st[++top].d1=dis[x];st[top].d2=dep[x];
for (int p=head[x];p;p=next[p])
if (!vis[to[p]] && to[p]!=fa[x]) dfs2(to[p]);
}
void calc(int x,int f)
{
top=0;
dfs2(x);
sort(st+1,st+top+1,cmp);
for (int i=1,j=top;i<=j;i++)
{
while (j>i && st[i].d1+st[j].d1>k) j--;
for (int p=j;st[i].d1+st[p].d1==k;p--) ans[st[i].d2+st[p].d2]+=f;
}
}
void solve(int x,int Size)
{
int cg;
fa[x]=0;
get_root(x,Size,cg);
size[fa[cg]]=Size-size[cg];
fa[cg]=0;vis[cg]=1;
dfs1(cg,0,0);
calc(cg,1);
for (int p=head[cg];p;p=next[p]) if (!vis[to[p]]) calc(to[p],-1);
for (int p=head[cg];p;p=next[p]) if (!vis[to[p]]) solve(to[p],size[to[p]]);
}
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++;
addedge(x,y,z);addedge(y,x,z);
}
solve(1,n);
for (int i=1;i<n;i++) if (ans[i]) {printf("%d\n",i);return 0;}
printf("-1\n");
return 0;
}