树上点分治就是利用重心的 性质进行分治
本题的合并原理是进行容斥操作
我们分三种情况去讨论
1如果点对在子树里 那么我们直接递归分治
2如果一点是重心 一个点 在子树 我们可以暴力求
3 如果两个点分别位于不同的子树
那么我们根据容斥原理
将所有的点对求出-在同一个子树里的点对进行分治
总的来说 树上点分治是一种 思想 (不是数据结构
被acwing上点分治模板卡了一个小时 一直tle 不懂
#include <bits/stdc++.h>
using namespace std;
//#define int long long
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define pb push_back
#define inf 1ll<<62
#define endl "\n"
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define de_bug(x) cerr << #x << "=" << x << endl
#define all(a) a.begin(),a.end()
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fer(i,a,b) for(int i=a;i<=b;i++)
#define der(i,a,b) for(int i=a;i>=b;i--)
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int n, m , k;
vector<pii> g[N];
int vis[N];
int q[N], p[N], cnt, idx2;
int get_sz(int u, int fa) {
if(vis[u])return 0;
int ans = 1;
for(auto a : g[u]) {
int v = a.fi;
if(v != fa)
ans += get_sz(v, u);
}
return ans;
}
int get_wc(int u, int fa, int tot, int wc) {
if(vis[u]) return 0;
int sum = 1;
int ma = -1;
for(auto a : g[u]) {
int v = a.fi;
if(v == fa)continue;
int t = get_wc(v, u, tot, wc);
ma = max(ma, t);
sum += t;
}
ma = max(ma, tot - sum);
if(ma <= tot / 2)wc = u;
return sum;
}
void get_d(int u, int fa, int dis, int &cnt) {
if(vis[u]) return ;
q[cnt++] = dis;
for(auto a : g[u]) {
int v = a.fi;
int w = a.se;
if(v == fa)continue;
get_d(v, u, dis + w , cnt);
}
}
int get_pre(int p[], int k) {
sort(p, p + k);
int ans = 0;
for(int i = k - 1, j = -1; i >= 0; i--) {
while(j + 1 < i && p[j + 1] + p[i] <= m)j++;
j = min(j, i - 1);
ans += j + 1;
}
return ans;
}
int get_ans(int u) {
if(vis[u])return 0;
int ans = 0;
get_wc(u, -1, get_sz(u, -1), u);
vis[u] = 1;
int idx1 = 0;
for(auto a : g[u]) {
int v = a.fi;
int w = a.se;
idx2 = 0;
get_d(v, -1, w, idx2);
ans -= get_pre(q, idx2);
for(int i = 0; i < idx2; i++) {
if(q[i] <= m) ans++;
p[idx1++] = q[i];
}
}
ans += get_pre(p, idx1);
for(auto a : g[u]) {
int v = a.fi;
ans += get_ans(v);
}
return ans;
}
void solve() {
cin >> n ;
//if((!n) && (!m))break;
for(int i = 0; i <= n; i++) {
vis[i] = 0;
// cnt=0;
g[i].clear();
}
for(int i = 0; i < n - 1; i++) {
int a, b, c;
cin >> a >> b >> c;
g[a].push_back({b, c});
g[b].push_back({a, c});
}
cin>>m;
cout << get_ans(1) << endl;
}
int main() {
IOS;
int _ = 1;
//cin>>_;
while( _-- )
solve();
}