E.All men are brothers
题目链接: https://ac.nowcoder.com/acm/contest/889/E
Problem Description
Amy asks Mr. B problem E. Please help Mr. B to solve the following problem.
There are n n n people, who don’t know each other at the beginning.
There are m m m turns. In each turn, 2 2 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.Input
The first line contains two integers, n n n and m ( n ≤ 100000 , m ≤ 200000 ) m (n \leq 100000, m \leq 200000) m(n≤100000,m≤200000), which are the number of people, and the number of turns.
In the following m m m lines, the i i i-th line contains two integers x x x and y ( 1 ≤ x ≤ n , 1 ≤ y ≤ n , x y ( 1 \leq x \leq n, 1 \leq y \leq n, x y(1≤x≤n,1≤y≤n,x ≠ y ) y) y) , which means the x x x-th person and the y y y-th person make friends in the i i i-th turn.
The x x x-th person and y y y-th person might make friends in several turns.Output
Output m + 1 m+1 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 m+1 m+1 lines.Sample Input
6 6
1 2
3 4
4 5
3 5
3 6
2 4Sample Output
15
9
4
0
0
0
0
题意
有 n n n个人, m m m回合。
在最开始的时候, n n n个人都相互不是朋友。此时输出一下从这 n n n个人中选 4 4 4个,且这 4 4 4个人都相互不是朋友的情况的数量,也就是 C n 4 ( n ≥ 4 ) C_n^4(n\geq4) Cn4(n≥4)或者 0 ( n < 4 ) 0(n\lt4) 0(n<4)。
接下来每回合给定 x x x和 y y y ( x (x (x ≠ y ) y) y),代表 x x x和 y y y成为朋友。若 A A A和 B B B为朋友,那么 A A A和 B B B的朋友也为朋友, B B B和 A A A的朋友也为朋友。每回合之后,再输出从这 n n n个人中选 4 4 4个,且这 4 4 4个人都相互不是朋友的情况的数量。
思路
若 A A A和 B B B为朋友,那么 A A A和 B B B的朋友也为朋友, B B B和 A A A的朋友也为朋友。这也就代表若 x x x和 y y y ( x (x (x ≠ y ) y) y) 在一个集合中就代表 x x x和 y y y ( x (x (x ≠ y ) y) y)为朋友,这可以用并查集来判断、连接 x x x和 y y y。
接下来最困难的问题就是计算若 x x x和 y y y不是朋友,变为朋友之后对答案的减少量。
很容易可以想到相比于上一次合并集合的方案数,这一次合并集合后方案数的减少量只与 x x x和 y y y的集合有关。
与 x x x和 y y y的集合有关的方案数有三类:
① ① ①选中的四个集合中包含 x x x所在集合,不包含 y y y所在集合。(合并 x , y x,y x,y集合后不影响,所以这个不必减少)
② ② ②选中的四个集合中包含 y y y所在集合,不包含 x x x所在集合。(合并 x , y x,y x,y集合后不影响,所以这个不必减少)
③ ③ ③选中的四个集合同时包含 x , y x,y x,y所在集合。(合并 x , y x,y x,y集合后该情况不符合条件,所以减少量为此情况的数量)
所以减少量 d d d就为 C c n t [ f x ] 1 ∗ C c n t [ f y ] 1 ∗ C_{cnt[fx]}^{1}*C_{cnt[fy]}^{1}* Ccnt[fx]1∗Ccnt[fy]1∗(除去 x , y x,y x,y集合中任选两个人不在同一集合的方案数),其中 c n t [ f x ] cnt[fx] cnt[fx]和 c n t [ f y ] cnt[fy] cnt[fy]分别为 x , y x,y x,y所在集合中的人数。
除去 x , y x,y x,y集合中任选两个人不在同一集合的方案数=除去 x , y x,y x,y集合的总人数中任选两个人减去在一个集合中选两个人的方案数的和。
除去 x , y x,y x,y集合的总人数中任选两个人的方案数就是 C t t 2 = t t ∗ ( t t − 1 ) 2 = t t ∗ t t − t t 2 ( 其 中 t t = n − c n t [ f x ] − c n t [ f y ] ) , C_{tt}^{2} = \frac {tt*(tt-1)}{2} = \frac {tt*tt-tt}{2}(其中tt = n-cnt[fx]-cnt[fy]), Ctt2=2tt∗(tt−1)=2tt∗tt−tt(其中tt=n−cnt[fx]−cnt[fy]),在一个集合中选两个人的方案数的和则为 ∑ i = 1 ( i 不 等 于 x 和 y ) n c n t [ f i ] ∗ ( c n t [ f i ] − 1 ) 2 = ∑ i = 1 ( i 不 等 于 x 和 y ) n c n t [ f i ] ∗ c n t [ f i ] − t t 2 \sum_{i=1(i不等于x和y)}^{n} \frac{cnt[fi]*(cnt[fi]-1)}{2} = \frac {\sum_{i = 1(i不等于x和y)}^ncnt[fi]*cnt[fi]-tt}{2} ∑i=1(i不等于x和y)n2cnt[fi]∗(cnt[fi]−1)=2∑i=1(i不等于x和y)ncnt[fi]∗cnt[fi]−tt。
所以除去 x , y x,y x,y集合中任选两个人不在同一集合的方案数= t t ∗ t t − t t 2 − ∑ i = 1 ( i 不 等 于 x 和 y ) n c n t [ f i ] ∗ c n t [ f i ] − t t 2 = t t ∗ t t − ∑ i = 1 ( i 不 等 于 x 和 y ) n c n t [ f i ] ∗ c n t [ f i ] 2 \frac {tt*tt-tt}{2}-\frac {\sum_{i = 1(i不等于x和y)}^ncnt[fi]*cnt[fi]-tt}{2} = \frac {tt*tt-\sum_{i = 1(i不等于x和y)}^ncnt[fi]*cnt[fi]}{2} 2tt∗tt−tt−2∑i=1(i不等于x和y)ncnt[fi]∗cnt[fi]−tt=2tt∗tt−∑i=1(i不等于x和y)ncnt[fi]∗cnt[fi]。
设 s u m sum sum最开始为 ∑ i = 1 n c n t [ f i ] 2 = n \sum_{i = 1}^{n}cnt[fi]^2 = n ∑i=1ncnt[fi]2=n,每次合并 x , y x,y x,y后 s u m sum sum减去 c n t [ f x ] 2 + c n t [ f y ] 2 cnt[fx]^2+cnt[fy]^2 cnt[fx]2+cnt[fy]2就可以等于 ∑ i = 1 ( i 不 等 于 x 和 y ) n c n t [ f i ] 2 \sum_{i = 1(i不等于x和y)}^ncnt[fi]^2 ∑i=1(i不等于x和y)ncnt[fi]2了,所以 t t ∗ t t − ∑ i = 1 ( i 不 等 于 x 和 y ) n c n t [ f i ] ∗ c n t [ f i ] 2 = t t ∗ t t − s u m 2 \frac {tt*tt-\sum_{i = 1(i不等于x和y)}^ncnt[fi]*cnt[fi]}{2} = \frac {tt*tt-sum}{2} 2tt∗tt−∑i=1(i不等于x和y)ncnt[fi]∗cnt[fi]=2tt∗tt−sum了,最后记得 s u m sum sum要加上 ( c n t [ f x ] + c n t [ f y ] ) 2 (cnt[fx]+cnt[fy])^2 (cnt[fx]+cnt[fy])2。
代码
#include <bits/stdc++.h>
#define pi acos(-1.0)
#define ll long long
#define ull unsigned long long
#define esp 1e-9
#define inf 0x3f3f3f3f
#define inff 0x3f3f3f3f3f3f3f3f
#define Pair pair<ll, ll>
#define It list<node>::iterator
using namespace std;
const ll N = 1e5+5;
ll n, m, x, y, ans, sum, f[N], cnt[N];
ll find(ll x){
return f[x]==x ? x : f[x]=find(f[x]);
}
int main(){
ios::sync_with_stdio(false);
while (cin>>n>>m){
for (ll i = 0; i <= n; i++){
f[i] = i; cnt[i] = 1;
}
ll tmp = n;
if (tmp < 4){//最开始就小于4个集合
ans = 0;
}
else{
ans = 1;
sum = n;//初始化sum为n
ll vis[5] = {0};
for (ll i = n; i >= n-3; i--){//计算最开始的方案数
ll t = i;
for (ll j = 2; j <= 4; j++){
if (!vis[j] && t%j==0){
vis[j] = 1;
t /= j;
}
}
ans *= t;
}
}
cout<<ans<<endl;
while (m--){
cin>>x>>y;
ll fx = find(x), fy = find(y), d = 0;
if (fx != fy){//x,y集合要合并
ll tt = n-cnt[fx]-cnt[fy];//计算除去x,y集合的总人数tt
sum -= (cnt[fx]*cnt[fx]+cnt[fy]*cnt[fy]);//更新sum
d = 1LL*cnt[fx]*cnt[fy]*((tt*tt-sum)/2);//计算方案的减少量
sum += ((cnt[fx]+cnt[fy])*(cnt[fx]+cnt[fy]));//sum加回(cnt[fx]+cnt[fy])*(cnt[fx]+cnt[fy])
tmp--;
f[fx] = fy;//将x合并进y所在集合
cnt[fy] += cnt[fx];//y所在集合人数加上x所在集合的人数
}
ans -= d;
cout<<ans<<endl;
}
}
return 0;
}