2019牛客暑期多校训练营(第九场) E.All men are brothers

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(n100000,m200000), 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(1xn,1yn,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 4

Sample 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(n4)或者 0 ( n &lt; 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]1Ccnt[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(tt1)=2tttttt(tt=ncnt[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(ixy)n2cnt[fi](cnt[fi]1)=2i=1(ixy)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} 2tttttt2i=1(ixy)ncnt[fi]cnt[fi]tt=2tttti=1(ixy)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(ixy)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} 2tttti=1(ixy)ncnt[fi]cnt[fi]=2ttttsum了,最后记得 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值