华南理工大学 “三七互娱杯” G HRY and tree

https://ac.nowcoder.com/acm/contest/874/G

题目大意:对于一个连通图,现在定义两个点的贡献为连接两点的路径上最大的权值 求任意两个点贡献的和

这个题看懂花了我很久的时间 真的难受

由于两个点的贡献是由最大的权值决定的,所以如果我们将边按权值由小到大排列,那么遍历的时候 当前的边一定是目前的最大权值 也就是两个点之间贡献

本题还用到了并查集来维护连通图

具体看代码吧

#include<bits/stdc++.h>
using namespace std;
#define maxn 1000000+1000
#define ull unsigned long long
 
int T,n,p[maxn],sz[maxn];
ull ans;
struct edge
{
    int u,v,w;
    bool operator<(edge x)   //运算符的重载 方便排序
    {
        return w<x.w;
    }
}e[max];
 
int findset(int x)
{
    return (x==p[x]?x:p[x]=findset(p[x]));    //并查集
}
 
int main()
{
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=1;i<n;i++)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
        sort(e+1,e+n);
        for(int i=1;i<=n;i++)p[i]=i;  //一开始是不连通的 分别标上号
        for(int i=1;i<=n;i++)sz[i]=1;  //所在连通图的大小
        ans=0;
        for(int i=1;i<n;i++)
        {
            int u=findset(e[i].u),v=findset(e[i].v); 
            ans+=(ull)sz[u]*sz[v]*e[i].w;   //增加的贡献
            sz[u]+=sz[v];  //扩大连通图
            p[v]=u; //标记连通图 注意要和上一行呼应 保证整合到同一个图里去
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/dyhaohaoxuexi/p/10858875.html
今日推荐