同样是点分治。。但是这题在合并的时候比较麻烦,假设重心为x,首先要从x向下求出子节点的深度,然后将子节点按深度排序,设排序后第
i
个点过重心能到的最远的点为第
#include<cstdio>
#include<iostream>
#include<memory.h>
#include<algorithm>
#define N 10005
#define clr(a) memset(a,0,sizeof(a))
using namespace std;
struct edge{
int e,q,next;
}ed[N*2];
int n,k,ne,ans,i,cnt,s,e,q,d[N],u[N],a[N],rt[N],ms[N],sz[N],f[N],st[N],g[N];
void add(int s,int e,int q)
{
ed[++ne].e=e;ed[ne].q=q;
ed[ne].next=a[s];a[s]=ne;
}
void init()
{
ne=ans=0;clr(a);clr(u);
}
int find(int x,int fa,int n)
{
sz[x]=1;ms[x]=rt[x]=0;
for (int j=a[x];j;j=ed[j].next)
if (!u[ed[j].e]&&ed[j].e!=fa)
{
find(ed[j].e,x,n);
sz[x]+=sz[ed[j].e];ms[x]=max(ms[x],sz[ed[j].e]);
if (ms[rt[ed[j].e]]<ms[rt[x]]) rt[x]=rt[ed[j].e];
}
ms[x]=max(ms[x],n-sz[x]);
if (ms[x]<ms[rt[x]]) rt[x]=x;
return rt[x];
}
void dfs(int x,int fa)
{
sz[x]=1;st[++cnt]=d[x];
for (int j=a[x];j;j=ed[j].next)
if (!u[ed[j].e]&&ed[j].e!=fa)
{
d[ed[j].e]=d[x]+ed[j].q;
dfs(ed[j].e,x);sz[x]+=sz[ed[j].e];
}
}
void work(int now,int n)
{
int x=find(now,-1,n);
cnt=1;st[1]=0;d[x]=0;u[x]=1;f[x]=g[x]=0;
for (int j=a[x];j;j=ed[j].next)
if(!u[ed[j].e])
{
d[ed[j].e]=ed[j].q;
dfs(ed[j].e,x);
}
sort(st+1,st+1+cnt);
int r=cnt;
for (int i=1;i<=cnt;i++)
{
while (st[r]+st[i]>k&&r>i) r--;
if (r<=i) break;
f[x]+=r-i;
}
for (int j=a[x];j;j=ed[j].next)
if (!u[ed[j].e])
{
d[ed[j].e]=ed[j].q;cnt=0;dfs(ed[j].e,x);
sort(st+1,st+1+cnt);
int r=cnt;
for (int i=1;i<=cnt;i++)
{
while (st[r]+st[i]>k&&r>i) r--;
if (r<=i) break;
f[x]-=r-i;
}
}
for (int j=a[x];j;j=ed[j].next)
if (!u[ed[j].e]) work(ed[j].e,sz[ed[j].e]);
ans+=f[x];
}
int main()
{
freopen("1741.in","r",stdin);
freopen("my.out","w",stdout);
ms[0]=1000000;
while(1)
{
scanf("%d%d",&n,&k);
if(n+k==0) return 0;
init();
for (i=1;i<n;i++)
{
scanf("%d%d%d",&s,&e,&q);
add(s,e,q);add(e,s,q);
}
work(1,n);
printf("%d\n",ans);
}
}