Path Queries 题解
lottle1212 · · 题解
原题传送门
题目描述
- 给出一棵
n (1 \leq n \leq 2 \times 10 ^ 5) 个节点的带权树。 - 请求出最大边权不超过
q (1 \leq q \leq 2 \times 10 ^ 5) 的简单路径数量。
分析
这是一道 并查集 好题。
首先,我们需要明白当第
题目中让我们求最大权值不大于
总时间复杂度为
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mxn = 2e5;
const int N = mxn + 10;
ll ans[N]; int n, m, fx, fy, sz[N], f[N], x;
struct node { int u, v, w; } e[N];
int get_fa(int x) { if(x == f[x]) return x; return f[x] = get_fa(f[x]); }
bool cmp(node pre, node nxt) { return pre.w < nxt.w; }
signed main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> m;
for(int i = 1; i < n; ++ i) cin >> e[i].u >> e[i].v >> e[i].w;
sort(e + 1, e + n, cmp);//对边按权值进行升序排序
for(int i = 1; i <= n; ++ i) f[i] = i, sz[i] = 1;//并查集初始化
for(int i = 1; i < n; ++ i) {
fx = get_fa(e[i].u), fy = get_fa(e[i].v);//求得祖先
ans[e[i].w] += (ll) sz[fx] * sz[fy];//计算贡献
f[fx] = fy, sz[fy] += sz[fx];//合并区块
}
for(int i = 1; i <= mxn; ++ i) ans[i] += ans[i - 1];//前缀求答案
while(m --) cin >> x, cout << ans[x] << ' ';
return 0;
}