Description
Give a tree with n vertices,each edge has a length(positive integer less than 1001).
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input
The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
The last test case is followed by two zeros.
Output
For each test case output the answer on a single line.
Sample Input
5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
Sample Output
8
树上的点分治:分块的思想,只不过这个分块是很讲究的,每次我们都去找一个块的重心(子树中最大子树的结点树最少),这样的话, 次就可以将整棵树都 拆完了。然后就是计数了,我们考虑所有合法的路径,对于每个树根,合法的路径,
为了速度,考虑直接计算两两相加小于K的所有组合,肯定是有不合法的,比如在同一课子树中选两个点,所以我们再减去所有不合法的,就是经过这个点的 <=2课子树的 情况了。
//#include<bits/stdc++.h>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define rep(i,a,b) for(int i=a;i<b;++i)
#define per(i,a,b) for(int i=b-1;i>=a;--i)
const int N=10010;
struct Edge{
int u,v,nt,w;
Edge(int _u=0,int _v=0,int _nt=0,int _w=0){
u=_u,v=_v,nt=_nt,w=_w;
}
}edge[N*2];
int head[N],cnt;
void add_edge(int u,int v,int w){
edge[cnt]=Edge(u,v,head[u],w);
head[u]=cnt++;
}
bool vis[N];
int n,K,sz[N];
int max_num,rt,tot;//最大子树的大小,子树祖先,子树大小
void get_rt(int u,int f){
sz[u]=1;int t=0;
for(int i=head[u];i!=-1;i=edge[i].nt){
Edge& e=edge[i];
if(vis[e.v]||e.v==f)continue;
get_rt(e.v,u);
sz[u]+=sz[e.v];
t=max(t,sz[e.v]);
}
t=max(t,tot-sz[u]);
if(t<max_num){
max_num=t,rt=u;
}
}
int deep[N],ans[N];
int rec[N];
void get_deep(int u,int f){
rec[++rec[0]]=deep[u];
for(int i=head[u];i!=-1;i=edge[i].nt){
Edge& e=edge[i];
if(vis[e.v]||e.v==f)continue;
deep[e.v]=deep[e.u]+e.w;
get_deep(e.v,u);
}
}
int solve(int u,int s){
rec[0]=0;
deep[u]=s;
get_deep(u,0);
sort(rec+1,rec+1+rec[0]);
//printf("\nu:%d\n",u);
//for(int i=1;i<=rec[0];i++)printf("i:%d rec:%d deep:%d\n",i,rec[i],deep[i]);
int l,r; int ans=0;
for(l=1,r=rec[0];l<r;++l){
while(rec[l]+rec[r]>K)r--;
if(l<=r){
ans+=r-l;
}
//printf("l:%d r:%d ans:%d\n",l,r,ans);
}
//printf("ans:%d\n",ans);
return ans;
}
void work(int u){
vis[u]=1;
ans[u]=solve(u,0);
for(int i=head[u];i!=-1;i=edge[i].nt){
Edge& e=edge[i];
if(vis[e.v])continue;
ans[u]-=solve(e.v,e.w);
rt=e.v,max_num=sz[e.v],tot=sz[e.v];
get_rt(e.v,rt);
work(rt);
}
}
int main(){
while(scanf("%d %d",&n,&K)==2){
if(!n&&!K)break;
cnt=0;
fill(head,head+n+1,-1);
fill(vis,vis+n+1,0);
rep(i,0,n-1){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
max_num=n,rt=1,tot=n;
get_rt(1,0);
// printf("rt:%d\n",rt);
work(rt);
//rep(i,1,n+1)printf("i:%d deep:%d\n",i,deep[i]);
int res=0;
for(int i=1;i<=n;i++)res+=ans[i];
printf("%d\n",res);
}
return 0;
}