#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
#define INPUT freopen("/Users/grh/Programming/CLionProjects/SimpleTest/input.txt", "r", stdin)
vector<pair<int, int>> link[10005];
int node_stat[10005]; // 节点是否存在
int tree_size[10005]; // 子树大小
int buf[10005]; // 路径的缓存
int buf_tot[10005]; // 路径的缓存
// 得到每一棵子树大小信息
int get_tree_size(int node, int prev) {
if (node_stat[node] == 0) {
return 0;
}
int sum = 1;
for (auto nei : link[node]) {
if (nei.first != prev && node_stat[nei.first] == 1) {
sum += get_tree_size(nei.first, node);
}
}
return sum;
}
// 求取重心, 函数返回子树的大小
int get_center(int node, int prev, int tot, int& center_node, int& min_wei) {
int ans = 1;
int wei = 0;
for (auto nei : link[node]) {
if (nei.first != prev && node_stat[nei.first] == 1) {
int sub_size = get_center(nei.first, node, tot, center_node, min_wei);
wei = max(wei, sub_size);
ans += sub_size;
}
}
wei = max(wei, tot - ans);
if (wei < min_wei) {
min_wei = wei;
center_node = node;
}
return ans;
}
int get_center(int node) {
int tot = get_tree_size(node, -1);
int center_node = -1, min_wei = 0x7fffffff;
get_center(node, -1, tot, center_node, min_wei);
return center_node;
}
int get_dis_lt_K_node_num(int node, int prev, int cur_dis, int K) {
if (cur_dis > K) {
return 0;
}
if (node_stat[node] == 0) {
return 0;
}
int ans = 1;
for (auto nei : link[node]) {
if (nei.first != prev && node_stat[nei.first] == 1) {
ans += get_dis_lt_K_node_num(nei.first, node, cur_dis + nei.second, K);
}
}
return ans;
}
void get_dis_lt_K_nodes(int node, int prev, int cur_dis, int K, int* buf, int& buf_size) {
if (cur_dis > K) {
return;
}
if (node_stat[node] == 0) {
return;
}
buf[buf_size++] = cur_dis;
for (auto nei : link[node]) {
if (nei.first != prev && node_stat[nei.first] == 1) {
get_dis_lt_K_nodes(nei.first, node, cur_dis + nei.second, K, buf, buf_size);
}
}
}
// 获取列表内总和小于K的数对的个数
int get_pair_cnt(int* buf, int buf_size, int K) {
sort(buf, buf + buf_size);
int ans = 0;
for (int i = 1; i < buf_size; i++) {
if (buf[i] >= K) {
break;
}
int l = 0, r = i-1, mid = 0;
int pos = -1;
while (l <= r) {
mid = (l + r) / 2;
if (buf[mid] <= K - buf[i]) {
pos = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
if (pos != -1) {
ans += pos + 1;
}
}
return ans;
}
int solve(int node, int K) {
if (node_stat[node] == 0) {
return 0;
}
int center_node = get_center(node);
int tot_ans = 0;
node_stat[center_node] = 0;
// 第一类点对,累加两个端点都在子树里面的点对
for (auto nei : link[center_node]) {
if (node_stat[nei.first] == 1) {
tot_ans += solve(nei.first, K);
}
}
// 第二类点对,一个端点在重心,另外一个端点在子树内部,只需要统计子树里面到重心的距离小于等于K的节点数量
for (auto nei: link[center_node]) {
if (node_stat[nei.first] == 1) {
tot_ans += get_dis_lt_K_node_num(nei.first, -1, nei.second, K);
}
}
// 第三类,两个端点分别在两个不同的子树内部, 用容斥原理来算个数,先统计每一个子树节点到重心的距离,
// 子树1得到距离列表dis1, 子树2得到距离列表dis2, .....
// 每一个dis列表中算距离和小于等于K的对数,这些对是不合法的
// 将dis1, dis2, ....全部合成一个大的距离列表,这个列表中算和小于等于K的对数是包含了合法的和不合法的
// 将算出来的总数减去不合法的的剩下的就是合法的第三类的点对的数量
int tot_size = 0;
for (auto nei: link[center_node]) {
if (node_stat[nei.first] == 1) {
int buf_size = 0;
get_dis_lt_K_nodes(nei.first, center_node, nei.second, K, buf, buf_size);
tot_ans -= get_pair_cnt(buf, buf_size, K);
for (int i = 0; i < buf_size; i++) {
buf_tot[tot_size++] = buf[i];
}
}
}
tot_ans += get_pair_cnt(buf_tot, tot_size, K);
node_stat[center_node] = 1;
return tot_ans;
}
int main() {
//INPUT;
int N, K;
int a, b, w;
while (true) {
scanf("%d %d", &N, &K);
if (N == 0 and K == 0) {
break;
}
for (int i = 0; i < N; i++) {
link[i].clear();
node_stat[i] = 1;
}
for (int i = 0; i < N-1; i++) {
scanf("%d %d %d", &a, &b, &w);
link[a].push_back(pair<int, int>{b, w});
link[b].push_back(pair<int, int>{a, w});
}
printf("%d\n", solve(0, K));
}
return 0;
}