题面:给定一颗包含n个顶点的树,第i条边连接u[i]和v[i],边权为w[i]。记f(i,j)表示顶点i到j的简单路径上边权的最大值,求f(i,j)之和,其中1 <= i < j <= n。
范围:2 <= n <= 1E5; 1 <= u[i],v[i] <= n; 1 <= w[i] <= 1E7
分析:对于每条边,考虑以它作为最大边权的路径数,为两侧节点数的乘积,数点可以用并查集维护,需要按边权从小到大的顺序处理。
#include <bits/stdc++.h>
using i64 = long long;
const int N = 100005;
int n, fa[N], sz[N];
std::tuple<int,int,int> e[N];
int leader(int x) {
return x == fa[x] ? x : fa[x] = leader(fa[x]);
}
void join(int x, int y) {
x = leader(x);
y = leader(y);
if (x != y) {
sz[x] += sz[y];
fa[y] = x;
}
}
void solve() {
std::cin >> n;
for (int i = 1; i < n; i++) {
int u, v, w;
std::cin >> u >> v >> w;
e[i] = {w, u, v};
}
std::sort(e + 1, e + n);
for (int i = 1; i <= n; i++) {
fa[i] = i;
sz[i] = 1;
}
i64 ans = 0;
for (int i = 1; i < n; i++) {
auto [w,u,v] = e[i];
u = leader(u);
v = leader(v);
ans += 1LL * w * sz[u] * sz[v];
join(u, v);
}
std::cout << ans << "\n";
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}
标签:并查集