**题目描述 **
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.
示例1
输入
6 6
1 2
3 4
4 5
3 5
3 6
2 4
输出
复制
15
9
4
0
0
0
0
示例2
输入
100000 0
输出
4166416671249975000
说明
Don’t use int.
思路
并查集记录朋友状态,记录任选2个和任选4个的方案总数,每次更新朋友状态后更新,输出任选4个的方案总数
代码实现
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
typedef long long ll;
const int N=100005;
const int INF=0x3f3f3f;
const ll mod=1e9;
int n,m,fa[N];
ll sum[N];
int vis[N];
ll C[N][5];
inline void init()
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
sum[i]=1;
}
for(int i=0;i<=n;i++) C[i][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=i&&j<=4;j++)
C[i][j]=C[i-1][j]+C[i-1][j-1];
}
inline int Find(int x)
{
if(x==fa[x]) return x;
return fa[x]=Find(fa[x]);
}
inline void Merge(int x,int y)
{
fa[Find(y)]=Find(x);
}
int main()
{
scanf("%d%d",&n,&m);
init();
ll ans4=C[n][4];
ll ans2=C[n][2];
printf("%lld\n",ans4);
int t=n;
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
if(Find(a)==Find(b))
{
printf("%lld\n",ans4);
continue;
}
int u=Find(a),v=Find(b);
ans4-=(ans2-sum[u]*sum[v]-(sum[u]+sum[v])*(n-sum[u]-sum[v]))*sum[u]*sum[v];
ans2-=sum[v]*sum[u];
sum[u]+=sum[v];
Merge(a,b);
printf("%lld\n",ans4);
}
return 0;
}