牛客暑期集训第九场E题(并查集)

https://ac.nowcoder.com/acm/contest/889/E
这是题目链接,方便大家参考题意,大致意思就是给你n个人,m个关系变化就是让两个人交朋友,在每一次变化后求出还有独立四个人的方案数。思路我都写在代码注释里拉,大家可以参考一下:

#include<bits/stdc++.h>
#pragma GCC optimize(3)
#define max(a,b) a>b?a:b
using namespace std;
typedef long long ll;
typedef long double ld;
const int N=1e5+5;
int n,m;
ld ans,cnt;
int fa[N];
ld num[N];
int find(int x){
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy){
        ld other=n-num[fx]-num[fy];
        ans=ans-num[fx]*num[fy]*(cnt-num[fx]*num[fy]-num[fx]*other-num[fy]*other);//这个意思就是考虑每次减少的方案数。
        //而减少的方案数一定就是从合并的两个集合各选出一个,然后再求出other里面选出两个的数量相乘,而other里面选出两个,求组合数肯定不行啦,那就得用原来的减去变少的。
        //而原来的为cnt变少的有三个部分一是这两个集合中各选出一个,就是num[fx]*num[fy],还有就是other里面选出一个在其余两个集合在各自选一个,这样就好理解啦。
        //ans=ans-num[fx]*num[fy]*(cnt-num[fx]*(n-num[fx])-num[fy]*(n-num[fy])+num[fx]*num[fy]);
        cnt=cnt-num[fx]*num[fy];
        fa[fx]=fy;
        num[fy]+=num[fx];//这里面num存储的是子节点的数量。
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) fa[i]=i,num[i]=1;
    ans=(ld)n*(n-1)*(n-2)*(n-3)/24;
    cnt=(ld)n*(n-1)/2;
    printf("%.0Lf\n",ans);
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        merge(u,v);
        printf("%.0Lf\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值