链接:https://ac.nowcoder.com/acm/contest/889/E
来源:牛客网
题目描述
Amy asks Mr. B problem E. Please help Mr. B to solve the following problem.
There are n people, who don't know each other at the beginning.
There are m turns. In each turn, 2 of them will make friends with each other.
The friend relation is mutual and transitive.
If A is a friend of B, then B is also a friend of A.
For example, if A is a friend of B, B is a friend of C, then A and C are friends.
At the beginning and after each turn, please calculate the number of ways to select four people from, such that any two of these four are not friends.
输入描述:
The first line contains two integers, n and m (n <= 100000, m <= 200000), which are the number of people, and the number of turns.
In the following m lines, the i-th line contains two integers x and y ( 1 <= x <= n, 1 <= y <= n, x ≠ y), which means the x-th person and the y-th person make friends in the i-th turn.
The x-th person and y-th person might make friends in several turns.
输出描述:
Output m+1 lines, each line contains an integer, which is the number of quadruples.
Output at the beginning and after each turn, so there are m+1 lines.
题目大意:现在给你N个人,给你M个关系,然后问你当第1~i条关系执行完后,找出4个人完全没关系的种类数
思路:这个题目当时比赛的时候没有想到他的那个怎么计算每一次的个数,没有做出来,下来以后看了大部分人的代码发现很多人都有着一样的公式,
我们现在推一下这个公式,比如现在有5个集合,a,b,c,d,e。
而且a和b是马上就要合并了的,那么我们现在的方案数到底减少了多少呢?
只看到减少的话,我么可以考虑a和b组成集合前的贡献,贡献也就是我们在a和b中选一个数,在其他的中选一个数,
那么就是 a*b(c*d+d*e+c*e),这也就是ab所做的贡献了,那么我们要把这个贡献去掉,就要把这个式子一般化
看了网上的大神的做法是这样的,
然后就是再化为一般话,令sum1为人数,sum2为人数和的平方和
然后就得到了这样的公式
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll unsigned long long
using namespace std;
const int maxn=100000+10;
ll c[maxn],sum1,sum2;
int F[maxn];
ll n,m;
int findset(int x)
{
if(F[x]==-1) return x;
return F[x]=findset(F[x]);
}
int main()
{
memset(F,-1,sizeof(F));
cin>>n>>m;
for(int i=1;i<=n;i++)
c[i]=1;
ll ans=n*(n-1)/2*(n-2)/3*(n-3)/4;
//cout<<" "<<ans<<endl;
sum1=n,sum2=n;
int x,y;
for(int i=1;i<=m;i++)
{
cout<<ans<<endl;
scanf("%d%d",&x,&y);
int fx=findset(x),fy=findset(y);
if(ans==0||fx==fy) continue;
F[fx]=fy;
ll a=c[fx],b=c[fy];
ans-=a*b*((sum1-a-b)*(sum1-a-b)-(sum2-a*a-b*b))/2;
sum2+=2*a*b;
c[fy]+=c[fx];
}
cout<<ans<<endl;
}