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

【题解】

题意:n个人,m次操作,每次操作使得两个人成为朋友,朋友的关系是可以传递的,计算执行每次操作后,选择四个人两两都不是朋友的不同方案的数目。

思路:一开始的选择数是 \textrm{C}_{n}^{4} ,然后我们来考虑每次减少的方案数:

假设要合并的是集合x和集合y,剩下的其他为z,那么减少的方案只有 x1+y1+z2 的情况。

为什么呢?

加入没有合并,总共有1.x1+z3 2.y1+z3 3.x1+y1+z2 4.z4 ,而合并之后独独少了第三种。

那么如何维护z2呢?

我们定义一个变量s存储每个集合Si的 C_{Si}^{2} 的和,那么我们需要减去的z2的数量就是 s-C_{x}^{2}-C_{y}^{2} .

【代码】

#include
using namespace std;
typedef unsigned long long ll;
const int N=1e5+10;
int f[N],c[N];
ll Find(int x)
{
    return f[x]==x?x:f[x]=Find(f[x]);
}
int main()
{
    ios::sync_with_stdio(0);
    for(int i=0;i>n>>m;
    ll ans=n*(n-1)/2*(n-2)/3*(n-3)/4,s=n;
    while(m--){
        cout<>u>>v;
        u=Find(u); v=Find(v);
        if(u==v||ans==0) continue;
        ll a=c[u],b=c[v];
        ans-=a*b*((n-a-b)*(n-a-b)-s+a*a+b*b)/2;
        s+=2*a*b;
        c[v]+=c[u];
        f[u]=v;
    }
    cout<

 

你可能感兴趣的:(2019牛客暑期多校训练营(第九场)E:All men are brothers(并查集+组合数学))