#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
/*
sz[x] 表示以x为根的子树的size使多少
son[x]表示x的儿子中size最大的是
rt 是我们要找的重心
all 当前子树的大小
*/
int sz[maxn],son[maxn],vis[maxn],dis[maxn];
int rt,all,ans,num;
int n,k;
int tot,head[maxn];
struct node{
int v,w,next;
}e[maxn];
void init(){
memset(head,-1,sizeof(head));
tot = 0;
memset(vis,0,sizeof(vis));
ans = 0;
}
void add(int u,int v,int w){
e[tot].w = w;
e[tot].v = v;
e[tot].next = head[u];
head[u] = tot++;
}
void getroot(int u,int fa){
sz[u] = 1;
son[u] = 0;
for(int i=head[u];i!=-1;i=e[i].next){
int v = e[i].v;
if(v==fa || vis[v]) continue;
getroot(v,u);
sz[u] += sz[v]; //将子树v的size加到u上
son[u] = max(son[u],sz[v]); //更新最大值
}
son[u] = max(son[u],all - sz[u]); //除了子树外的那部分
if(son[rt] > son[u] || son[rt] == 0) rt = u;// 更新rt
}
void getdis(int u,int fa,int dist){//得到当前子树里每个点到子树根的距离
dis[++num] = dist;
for(int i=head[u];i!=-1;i=e[i].next){
int v = e[i].v;
if(v == fa || vis[v]) continue;
getdis(v,u,dist + e[i].w);
}
}
void cal(int u,int op,int initv){
//op +1or-1 代表是加还是减,即减去不合法的。
num = 0;
getdis(u,0,initv); //得到dis数组
sort(dis+1,dis+1+num);
int res = 0;
int l = 1, r = num;
while(l < r){ //two-point 统计答案
while(dis[l] + dis[r] > k && l < r)r--;
res += r-l;
l++;
}
ans += op * res; //更新答案op的值是+1或-1
}
void solve(int u){
rt = 0;getroot(u,0);u = rt;//得到当前子树的重心
cal(u,1,0); //计算包含根的答案
vis[u] = 1;//删除该根
for(int i=head[u];i!=-1;i=e[i].next){
int v = e[i].v;
if(vis[v]) continue;
cal(v,-1,e[i].w); //减去同子树合并的不合法答案
all = sz[v]>sz[u]?all-sz[u]:sz[v];
solve(v); //递归统计子树的答案
}
}
int main(){
while(scanf("%d%d",&n,&k) && k+n){
init();
for(int i=1;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
all = n;
solve(1);
printf("%d\n",ans);
}
return 0;
}