显示代码纯文本
#include<cstdio>
#include<vector>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int SIZEN=10020;
vector<pair<int,int> > s[SIZEN];
int N,K,root;
bool vis[SIZEN];
int siz[SIZEN],pos[SIZEN];
int cnt;//当前子树的大小
bool read()
{
scanf("%d%d",&N,&K);
if(N==0&&K==0) return 0;
int u,v,l;
memset(vis,0,sizeof(vis));
for(int i=1;i<=N;i++) s[i].clear();
for(int i=1;i<N;i++)
{
scanf("%d%d%d",&u,&v,&l);
s[u].push_back(make_pair(v,l));
s[v].push_back(make_pair(u,l));
}
return 1;
}
void getroot(int x,int fa)//寻找树的重心
{
pos[x]=0,siz[x]=1;
for(int i=0;i<s[x].size();i++)
{
int v=s[x][i].first;
if(v==fa||vis[v]) continue;
getroot(v,x);
siz[x]+=siz[v];
pos[x]=max(pos[x],siz[v]);
}
pos[x]=max(cnt-siz[x],pos[x]);
if(!root||pos[x]<pos[root]) root=x;
}
int tot;
int dep[SIZEN],dis[SIZEN];
void getdep(int x,int fa)//得到x到其子树内部各点的距离
{
//为了减少之后排序的时间复杂度,在这里使用了dep
dep[tot++]=dis[x];
for(int i=0;i<s[x].size();i++)
{
int v=s[x][i].first;
if(v==fa||vis[v]) continue;
dis[v]=dis[x]+s[x][i].second;
getdep(v,x);
}
}
int clac(int x,int lo)
{
dis[x]=lo;
tot=0;
getdep(x,0);
sort(dep,dep+tot);
int ans=0,r=tot-1,l=0;
while(l<r)
{
while(r>l&&dep[r]+dep[l]>K) r--;
ans+=r-l;
l++;
}
return ans;
}
int TC(int x)//将以x为根的子树分治
{
int ans=0;
vis[x]=1;
ans+=clac(x,0);
for(int i=0;i<s[x].size();i++)
{
int v=s[x][i].first;
if(!vis[v])
{
ans-=clac(v,s[x][i].second);
root=0;cnt=siz[v];getroot(v,0);
ans+=TC(root);
}
}
//cout<<x<<" "<<ans<<endl;
return ans;
}
void work()
{
root=0;cnt=N;getroot(1,0);
printf("%d\n",TC(root));
}
int main()
{
freopen("poj1741_tree.in","r",stdin);
freopen("poj1741_tree.out","w",stdout);
while(read())
{
work();
}
return 0;
}