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;
}

 

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