ABC214 D - Sum of Maximum Weights(并查集+图论)

目录

Description

有一棵树,计算 \(\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}f(i,j)\), 其中 \(f(i,j)\) 代表 \(i,j\) 两个节点之间最短路径上的最大边权

State

\(1<=n<=10^{5}\)

\(1<=u,v<=n\)

\(1<=w<=10^7\)

Input

5
1 2 1
2 3 2
4 2 5
3 5 14

Output

76

Solution

题目属于贡献题,即每条边对答案的贡献是是多少

看一下样例中的 \(2,4\) 这条边,边权 \(x=5\) 对答案的贡献为 \(3x\) ,不难发现,较大的边权会将较小的边权覆盖,所以按照边权顺序来;

一条边左右两个端点各形成两棵树,而且边权一定小,所以这两棵树的大小相乘便是这条边的贡献

Code

const int N = 2e5 + 5;

    ll n, m, _;
    int i, j, k;
    tuple<int, int ,int> a[N];
    int fa[N];
    int sz[N];

int Find(int x)
{
    if(x == fa[x]) return x;
    else return fa[x] = Find(fa[x]);
}

void Union(int x, int y)
{
    int nx = Find(x), ny = Find(y);
    if(nx != ny){
        fa[nx] = ny;
        sz[ny] += sz[nx];
    }
    return void();
}

signed main()
{
    //IOS;
    while(~ sd(n)){
        rep(i, 1, n){
            fa[i] = i;
            sz[i] = 1;
        }
        rep(i, 1, n - 1){
            sddd(get<1>(a[i]), get<2>(a[i]), get<0>(a[i]));
        }
        sort(a + 1, a + 1 + n);
        ll ans = 0;
        rep(i, 1, n){
            int x = Find(get<1>(a[i])), y = Find(get<2>(a[i]));
            ans += (ll)sz[x] * sz[y] * get<0>(a[i]);
            Union(x, y);
        }
        pll(ans);
    }
    //PAUSE;
    return 0;
}
上一篇:类模板学习20210921


下一篇:编程题三:使用指针来打印数组内容