2019牛客暑期多校训练营(第九场) E All men are brothers 并查集+组合数

题意:n个人,好友关系可以相互传递,每次给一个x和y让他们交朋友,问你每次交朋友后有多少选择能取出四个人,这四个人互不为好友

题解:用并查集维护集合大小,然后每次减去相应的组合数就可以

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mem(s) memset(s, 0, sizeof(s))
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 1e6+5;
const int mod = 998244353;
int pre[maxn],sum[maxn];
int n,m;
void init(){
    for(int i=0;i<=n;i++)pre[i]=i,sum[i]=1;
}
int Find(int x){
    return pre[x]==x?x:pre[x]=Find(pre[x]);
}
int main() 
{
    scanf("%d%d",&n,&m);
    init();
    ll ans=(__int128)n*(n-1)*(n-2)*(n-3)/4/3/2;
    ll c2=(__int128)n*(n-1)/2;//n个人取两个
    printf("%lld\n",ans);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        int fx=Find(x),fy=Find(y);
        if(fx==fy){
            printf("%lld\n",ans);
            continue;
        }
        ull num=n-sum[fx]-sum[fy];
        ull temp=c2-sum[fx]*num-sum[fy]*num-sum[fx]*sum[fy];//n个人取两个减去一个集合*一个外面,一个集合*一个外面,两个集合*,剩下的就是两个都是外面的
        ans-=sum[fx]*sum[fy]*temp;//减去一个集合*一个集合*两个外面(可行方案),就是剩下的方案数
        c2-=sum[fx]*sum[fy];//减去两个都在集合内,因为这两个合并了
        pre[fx]=fy;
        sum[fy]+=sum[fx];
        printf("%lld\n",ans);
    
    }    
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章