#include #include #include using namespace std; // 建议使用 N 定义数组,比 vector 稍快且容易管理 const int N = 100005; vector> adj[N]; bool vis[N]; // 分治标记:记录哪些点已经作为重心被“删掉”了 int treesize[N]; int root, min_maxpart, K; long long ans = 0; // 存储当前子树所有节点到重心的距离 vector dists; // 1. 找重心:注意这里不再需要 visited 数组,用 fa 限制方向即可 void get_root(int u, int fa, int currsize) { treesize[u] = 1; int maxpart = 0; for (auto& edge : adj[u]) { int v = edge.first; if (v == fa || vis[v]) continue; // 关键:不能走已经“删掉”的点 get_root(v, u, currsize); treesize[u] += treesize[v]; maxpart = max(maxpart, treesize[v]); } maxpart = max(maxpart, currsize - treesize[u]); if (maxpart < min_maxpart) { min_maxpart = maxpart; root = u; } } // 2. 收集距离:把所有节点到重心的距离存入 dists 数组 void get_dists(int u, int fa, int d) { dists.push_back(d); for (auto& edge : adj[u]) { int v = edge.first; int w = edge.second; if (v == fa || vis[v]) continue; get_dists(v, u, d + w); } } // 3. 计算贡献:双指针法统计满足 dist1 + dist2 <= K 的对数 long long calc(int u, int init_dist) { dists.clear(); get_dists(u, -1, init_dist); sort(dists.begin(), dists.end()); long long count = 0; int l = 0, r = dists.size() - 1; while (l < r) { if (dists[l] + dists[r] <= K) { count += (r - l); l++; } else { r--; } } return count; } // 4. 点分治主函数 void divide(int u, int currsize) { // 每次进入先找当前连通块的重心 min_maxpart = currsize + 7; // 初始化为一个大值 get_root(u, -1, currsize); int r = root; // 锁定重心 vis[r] = true; // 【关键】逻辑切断重心 // 统计经过重心的路径 ans += calc(r, 0); // 递归子树 for (auto& edge : adj[r]) { int v = edge.first; int w = edge.second; if (vis[v]) continue; // 【关键】去重:减去在同一个儿子子树内提前满足条件的路径 ans -= calc(v, w); // 这里的 currsize 要更新为子树的实际大小 // 注意:由于已经跑过 get_root,treesize[v] 此时就是正确的 // 但如果 v 是 r 的“上方”节点,size 应该是 currsize - treesize[r] int next_size = (treesize[v] < treesize[r]) ? treesize[v] : (currsize - treesize[r]); divide(v, next_size); } } int main() { int n; if (!(cin >> n >> K)) return 0; for (int i = 0; i < n - 1; i++) { int u, v, w; cin >> u >> v >> w; adj[u].push_back({v, w}); adj[v].push_back({u, w}); } divide(1, n); // 从节点1开始分治,总大小为 n cout << ans << endl; return 0; }