// poj1741
struct edge{
int v, w, next;
}e[maxn*2];
int head[maxn], cnt;
void add(int u, int v, int w)
{
e[cnt].v = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt++;
}
int sz[maxn], vis[maxn], mx, size, root;
ll d[maxn], q[maxn], l, r;
void getroot(int u, int fa) // 找树的重心
{
sz[u] = 1; int num = 0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v = e[i].v;
if(v==fa||vis[v]) continue;
getroot(v, u);
sz[u] += sz[v];
num = max(num, sz[v]);
}
num = max(num, size-sz[u]);
if(num<mx) {mx = num; root = u;}
}
void getdis(int u, int fa) // 计算以u为根的子树上的距离(根据题目要求变化)
{
q[++r] = d[u];
for(int i=head[u];i!=-1;i=e[i].next)
{
int v = e[i].v;
if(v==fa||vis[v]) continue;
d[v] = d[u] + e[i].w;
getdis(v, u);
}
}
ll calc(int u, int val)
{
r = 0;
d[u] = val;
getdis(u, 0);
ll sum = 0; l = 1;
sort(q+1, q+r+1);
while(l<r)
{
if(q[l]+q[r]<=k) {sum+= r-l; l++;}
else --r;
}
return sum;
}
ll ans = 0;
void dfs(int u)
{
ans += calc(u, 0);
vis[u] = 1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v = e[i].v;
if(vis[v]) continue;
ans -= calc(v, e[i].w);
size = sz[v];
mx = 0x3f3f3f3f;
getroot(v, 0);
dfs(root);
}
}
int main()
{
ios::sync_with_stdio(false);
while(1){
cin >> n >> k;
if(!n) break;
memset(head, -1, sizeof head);
for(int i=0;i<n-1;i++)
{
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
add(v, u, w);
}
memset(vis, 0, sizeof vis);
ans = 0;
size = n; mx = 0x3f3f3f3f;
getroot(1, 0);
dfs(root);
cout << ans << endl;
}
return 0;
}
【模板】点分治
最新推荐文章于 2024-09-06 10:38:06 发布