[并查集]LibreOJ#10067 构造完全图 题解

版权声明:本文为博主原创文章,欢迎转载。 https://blog.csdn.net/try__jhf/article/details/82596211

题目大意

见题目……

解题报告

完全不会做啊……

从边入手这道题.

把每条边所连的左右两个点分别看做一个集合,左边集合和右边集合所要连的边数是(cnt[i]*cnt[j]-1)。

但我们要连的边权是多大?不能比当前的边还小,所以边权就为(当前边的边权+1),我们可以贪心的去解决,把边从小到大排序,并查集一下就行了,当然还得加上原始边的边权。

全是抄的……

示例代码

LibreOJ10067

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100005;
int n,fa[maxn],cnt[maxn];
LL ans;
struct data{
    int x,y,z;
    data (int x=0,int y=0,int z=0):x(x),y(y),z(z){}
    bool operator < (const data b)const{return z<b.z;}
}a[maxn];
inline void readi(int &x){
    x=0; char ch=getchar();
    while ('0'>ch||ch>'9') ch=getchar();
    while ('0'<=ch&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
}
int getf(int x){return (fa[x]==x)?x:fa[x]=getf(fa[x]);}
int main()
{
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    readi(n); ans=0;
    for (int i=1,x,y,z;i<n;i++){
        readi(x); readi(y); readi(z);
        a[i]=data(x,y,z); ans+=z;
    }
    sort(a+1,a+n); for (int i=1;i<=n;i++) {fa[i]=i; cnt[i]=1;}
    for (int i=1,fx,fy;i<n;i++){
        fx=getf(a[i].x); fy=getf(a[i].y);
        ans+=(LL)(a[i].z+1)*((LL)cnt[fx]*cnt[fy]-1);
        fa[fy]=fx; cnt[fx]+=cnt[fy];
    }
    printf("%lld",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/try__jhf/article/details/82596211