2019 Niuko Summer Multi-School Training Camp (Ninth) E All men are brothers 【And check + thinking】

Title description

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.

Enter description 

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 description 

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.

Example input 1 

6 6
1 2
3 4
4 5
3 5
3 6
2 4

Example output 1 

15
9
4
0
0
0
0

Example input 2 

100000 0

Sample output 2 

4166416671249975000

Explanation 

Don't use int.

The main idea:

There are n people, perform m operations. Each operation makes two people friends, and the relationship between the friends can be transferred, that is, when the two people become friends, everyone who is friends with the two people becomes friends.

After performing each operation, select the number of different programs in which four people are not friends.

analysis:

From the operations in the title and the transitivity of the relationship, it is conceivable to use and check set maintenance, while maintaining the number of elements in each set.

In the initial state, the number of solutions is  C_n^4 , we consider the number subtracted in each operation.

The scheme for each subtraction is to select one of the two current sets, and in addition, select one of the two sets from the other sets. Suppose the number of elements in the two combined sets is a and b, then the number of subtraction each time = a * b * (select two elements from other sets, and the two elements are not in the same set of plans).

To find the number of solutions in which two elements are selected from other collections, and the two elements are not in the same collection, you can first find the number of alternatives, and then subtract the number of solutions from the same collection.

Therefore, we can maintain a tmp value during each operation tmp=\sum_{i=1}^{k}C_{size[i]}^2, (size [i] is the number of elements in each set), and record the number of options for selecting two elements in the same set in the current state.

See the code for specific explanation.

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ll;

const ll maxn=100005;

ll fa[maxn],size[maxn];

//并查集的Get操作 
ll get(ll x){
	if(fa[x]==x)  return x;
	return fa[x]=get(fa[x]);
}

//并查集的Merge操作
void merge(ll x,ll y){
	ll fx=get(x),fy=get(y); 
	fa[fy]=fx;
	size[fx]=size[fx]+size[fy];
}

//计算每个集合中选择两个元素的方案数 
ll getCi2(ll num){
	if(num<2)  return 0;
	else  return num*(num-1)/2;
}

int main(){
	ll n,m;
	scanf("%lld%lld",&n,&m);
	ll x,y;
	//初始化 
	for(ll i=1;i<=n;i++){
		fa[i]=i;
		size[i]=1;
	}
	//n<4要单独判断 
	if(n<4){
		for(ll i=1;i<=(m+1);i++){
			printf("0\n"); 
		}
		return 0;
	}
	ll ans=n*(n-1)/2*(n-2)/3*(n-3)/4;//这里要注意不能按下行的方式写,否则中间结果会溢出unsigned long long 
//	ll ans=(n*(n-1)*(n-2)*(n-3))/(24);
	printf("%lld\n",ans); 
	ll tmp=0;//维护的tmp值 
	for(ll i=1;i<=m;i++){
		scanf("%lld%lld",&x,&y);
		ll fx=get(x),fy=get(y);
		if(fx==fy){//若两个人已经是朋友,不做操作 
			printf("%lld\n",ans);
			continue;
		}
		//减去当前两个集合下的方案数 
		tmp-=getCi2(size[fx]);
		tmp-=getCi2(size[fy]);
		ans-=size[fx]*size[fy]*((n-size[fx]-size[fy])*(n-size[fx]-size[fy]-1)/2-tmp);
		printf("%lld\n",ans);
		tmp+=getCi2(size[fx]+size[fy]);//更新tmp值 
		merge(x,y);//合并两个集合 
	}
	return 0;
} 

 

Published 30 original articles · won 5 · 900 views

Guess you like

Origin blog.csdn.net/qq_42840665/article/details/99682386