Solution - P4178 Tree
咕。好像要吃 flag 了。
思路
淀粉质模板题(的变形),不难。
淀粉质都会吧。点分治出来以后用双指针干出路径个数就行了。注意同子树的情况。
代码
#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 40004
using namespace std;
int to[N<<1], val[N<<1], nxt[N<<1], head[N], gsiz = 1;
#define mkarc(u,v,w) (++gsiz, to[gsiz]=v, val[gsiz]=w, nxt[gsiz]=head[u], head[u]=gsiz)
int siz[N], vis[N], dis[N], tmp[N], cnt, cntt;
int n, k;
int ans;
inline void dfs1(rint u, rint fa){
siz[u] = 1;
for(rint i = head[u]; i; i = nxt[i]){
rint v = to[i];
if(v == fa || vis[v]) continue;
dfs1(v, u);
siz[u] += siz[v];
}
return;
}
inline void dfs2(rint u, rint fa, rint root, rint& minn, rint& k){
rint mink = siz[root]-siz[u];
for(rint i = head[u]; i; i = nxt[i]){
rint v = to[i];
if(v == fa || vis[v]) continue;
mink = max(mink, siz[v]);
dfs2(v, u, root, minn, k);
}
if(mink < minn) k = u;
return;
}
inline void dfs3(rint u, rint fa, rint dep){
tmp[++cntt] = dep;
for(rint i = head[u]; i; i = nxt[i]){
rint v = to[i];
if(v == fa || vis[v]) continue;
dfs3(v, u, dep+val[i]);
}
return;
}
inline void solve(rint u){
//puts("QFR");
cnt = 0;
rint minn = 1e9+7, g;
dfs1(u, 0);
dfs2(u, 0, u, minn, g);
vis[g] = true;
rint delta = 0, res = 0;
dis[++cnt] = 0;
for(rint e = head[g]; e; e = nxt[e]){
cntt = 0;
rint v = to[e];
if(vis[v]) continue;
dfs3(v, u, val[e]);
sort(tmp+1, tmp+cntt+1);
rint l = 1, r = cntt;
while(l <= r){
while(l <= r && tmp[l]+tmp[r] > k) --r;
if(l <= r) delta += (r-l+1), ++l;
}
for(rint i = 1; i <= cntt; ++i)
dis[++cnt] = tmp[i];
}
sort(dis+1, dis+cnt+1);
rint l = 1, r = cnt;
while(l <= r){
while(l <= r && dis[l]+dis[r] > k) --r;
if(l <= r) res += (r-l+1), ++l;
}
ans += res-delta-1;
for(rint i = head[g]; i; i = nxt[i])
if(!vis[to[i]]) solve(to[i]);
return;
}
int main(){
scanf("%d", &n);
for(rint i = 1; i < n; ++i){
rint u, v, w;
scanf("%d %d %d", &u, &v, &w);
mkarc(u, v, w), mkarc(v, u, w);
}
scanf("%d", &k);
solve(1);
printf("%d", ans);
return 0;
}