abc214D 全部路径最大边权之和

57 阅读1分钟

题面:给定一颗包含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;
}

标签:并查集