rt,后四个点WA
#include <cstdio>
#include <iostream>
#define int long long
#define maxn 2000005
using std::max;
inline char nc () {
static char buf[1 << 21], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread (buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read () {
register int x(0), f(1); char ch = nc ();
while (ch < '0' || ch > '9') {if (ch == '-') f = -f; ch = nc ();}
while (ch >= '0' && ch <= '9') {x = x*10 + ch-'0'; ch = nc ();}
return x * f;
}
template <class I>
class fhq{
private:
int Root, cnt;
struct T{
int lson, rson, key, rnd, sz;
}t[1000000];
public:
inline int make(int k){
int root = ++cnt;
t[root].lson = t[root].rson = 0;
t[root].key = k;
t[root].rnd = rand();
t[root].sz = 1;
return root;
}
inline void update(int root){
t[root].sz = t[t[root].lson].sz + t[t[root].rson].sz + 1;
}
inline void split(int root, int k, int &x, int &y){
if(!root){
x = y = 0;
return;
}
if(t[root].key <= k){
x = root;
split(t[root].rson, k, t[root].rson, y);
}
else{
y = root;
split(t[root].lson, k, x, t[root].lson);
}
update(root);
}
inline int merge(int x, int y){
if(!x | !y){
return x | y;
}
if(t[x].rnd < t[y].rnd){
t[x].rson = merge(t[x].rson, y);
update(x);
return x;
}
else{
t[y].lson = merge(x, t[y].lson);
update(y);
return y;
}
}
inline void add(int k){
int x, y;
split(Root, k - 1, x, y);
Root = merge(merge(x, make(k)), y);
}
inline void del(int k){
int x, y, z;
split(Root, k, x, z);
split(x, k - 1, x, y);
if(y) y = merge(t[y].lson, t[y].rson);
Root = merge(merge(x, y), z);
}
inline int lower(int k){
int x, y, ans;
split(Root, k - 1, x, y);
ans = t[x].sz;
Root = merge(x, y);
return ans;
}
};
fhq < int > t;
struct Edge{
int start, end, val, nxt;
}edge[maxn << 1];
int cnt_edge, head[maxn];
inline void add_edge(int u, int v, int w){
edge[++cnt_edge] = (Edge){u, v, w, head[u]};
head[u] = cnt_edge;
}
int rem[maxn], sz[maxn], ans;
int n, m, rt, tot, maxp[maxn];
int top, dis[40000005], que[maxn];
bool have[40000005], vis[maxn];
int u, v, w, q;
inline void get_dis(int u, int f){
rem[++rem[0]] = dis[u];
for(int i = head[u]; i; i = edge[i].nxt){
int v = edge[i].end;
if(v == f || vis[v]) continue;
dis[v] = dis[u] + edge[i].val;
get_dis(v, u);
}
}
inline void get_rt(int u, int f){
sz[u] = 1, maxp[u] = 0;
for(int i = head[u]; i; i = edge[i].nxt){
int v = edge[i].end;
if(v == f || vis[v]) continue;
get_rt(v, u);
sz[u] += sz[v];
maxp[u] = max(maxp[u], sz[v]);
}
maxp[u] = max(maxp[u], tot - sz[u]);
if(maxp[u] < maxp[rt]) rt = u;
}
inline void work(int u){
for(int i = head[u]; i; i = edge[i].nxt){
int v = edge[i].end;
if(vis[v]) continue;
rem[0] = 0, dis[v] = edge[i].val;
get_dis(v, u);
for(int j = rem[0]; j; j--){
if(q >= rem[j]){
ans += t.lower(q - rem[j]);
}
}
for(int j = rem[0]; j; j--){
t.add(rem[j]);
que[++top] = rem[j];
}
}
while(top){
t.del(que[top--]);
}
t.del(0);
}
inline void divide(int u){
vis[u] = 1;
t.add(0);
work(u);
for(int i = head[u]; i; i = edge[i].nxt){
int v = edge[i].end;
if(vis[v]) continue;
tot = maxp[rt = 0] = sz[v];
get_rt(v, 0);
get_rt(rt, 0);
divide(rt);
}
}
signed main(){
n = read();
for(int i = 1; i < n; i++){
u = read(); v = read(); w = read();
add_edge(u, v, w);
add_edge(v, u, w);
}
q = read();
maxp[rt] = tot = maxn;
get_rt(1, 0);
get_rt(rt, 0);
divide(rt);
printf("%lld\n", ans);
return 0;
}