2019第16届浙江省赛——J - Welcome Party (并查集 + 建图)

Welcome Party (并查集 + 建图)

The 44th World Finals of the International Collegiate Programming Contest (ICPC 2020) will be held in Moscow, Russia. To celebrate this annual event for the best competitive programmers around the world, it is decided to host a welcome party for all participants of the World Finals, numbered from to for convenience.

The party will be held in a large hall. For security reasons, all participants must present their badge to the staff and pass a security check in order to be admitted into the hall. Due to the lack of equipment to perform the security check, it is decided to open only one entrance to the hall, and therefore only one person can enter the hall at a time.

Some participants are friends with each other. There are pairs of mutual friendship relations. Needless to say, parties are more fun with friends. When a participant enters the hall, if he or she finds that none of his or her friends is in the hall, then that participant will be unhappy, even if his or her friends will be in the hall later. So, one big problem for the organizer is the order according to which participants enter the hall, as this will determine the number of unhappy participants. You are asked to find an order that minimizes the number of unhappy participants. Because participants with smaller numbers are more important (for example the ICPC director may get the number 1), if there are multiple such orders, you need to find the lexicographically smallest one, so that important participants enter the hall first.

Please note that if participant and are friends, and if participant and are friends, it’s NOT necessary that participant and are friends.

Input

There are multiple test cases. The first line of the input contains a positive integer , indicating the number of cases. For each test case:

The first line contains two integers and (), the number of participants and the number of friendship relations.

The following lines each contains two integers and (), indicating that the -th and the -th participant are friends. Each friendship pair is only described once in the input.

It is guaranteed that neither the sum of nor the sum of of all cases will exceed .

Output

For each case, print a single integer on the first line, indicating the minimum number of unhappy participants. On the second line, print a permutation of to separated by a space, indicating the lexicographically smallest ordering of participants entering the hall that achieves this minimum number.

扫描二维码关注公众号,回复: 6136797 查看本文章

Consider two orderings and , we say is lexicographically smaller than , if there exists an integer (), such that holds for all , and .

Please, DO NOT output extra spaces at the end of each line, or your solution may be considered incorrect!

Sample Input

2
4 3
1 2
1 3
1 4
4 2
1 2
3 4
Sample Output

1
1 2 3 4
2
1 2 3 4

题目大意:

有n个人(编号1-n)去参加聚会,有m对关系,每对关系由俩数 a ,b组成,表示a b是朋友。注意:a b是朋友 b c是朋友,a c不一定是朋友,在这里这个朋友没有传递性。
如果一个人进入会场,然而会场里没有一个他的朋友,他就会不开心。然后每个人的编号越小,这个人就越重要。
要求:让不开心的人数最少,输出入场顺序。如果有多种情况,数组字典序最小的结果。

解题思路:

把有朋友关系的连边,放入一个并查集里。并的时候,要大的向小的靠拢,有多少联通快,就输出多少不开心的人。在每个连通块里面,最小的那个点就是根节点。
首先把所有的根放入优先队列里(保证相同的状态下小的先输出),每次出对列一个,并输出,那这个点所连的边就都可以入队了,因为这个人进去了,他的朋友们再进就不会不开心了。一直出到没人为止。

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int head[maxn];
int vis[maxn];
int ans[maxn];
int cnt=0;
int f[maxn];
int n,m;
priority_queue<int,vector<int>,greater<int> > q;
struct node{
	int to;
	int next;
}side[maxn*2];
int find(int x){
	if(x == f[x]) return f[x];
	else return f[x]=find(f[x]);
}
void merge(int x,int y){
	int fx=find(x);
	int fy=find(y);
	if(fx==fy) return;
	else{
		if(fx<fy){
			f[fy]=fx;
		}
		else{
			f[fx]=fy;
		}
	}
	return ;
}
void add(int x,int y){
	side[cnt].to=y;
	side[cnt].next=head[x];
	head[x] = cnt++;
}
void init(){
	for(int i=0;i<=n+1;i++){
		vis[i]=0;
		head[i]=-1;
		f[i]=i;
	}
	cnt=0;;
} 
int Ans=0;
void in_queue(){
	while(q.size()) q.pop();
	Ans=0;
	for(int i=1;i<=n;i++){
		if(f[i]==i){
			Ans++;
			q.push(i);
		}
	}
} 
int main()
{
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		init();
		for(int i=0;i<m;i++){
			int a,b;
			scanf("%d%d",&a,&b);
			add(a,b);
			add(b,a);
			merge(a,b);
		}
		in_queue();
		int ss=0;
		while(q.size()){
			int now = q.top();
			q.pop();
			if(vis[now]) continue;
			vis[now]=1;
			ans[ss++]=now;
			for(int i=head[now];i!=-1;i=side[i].next){
				int t=side[i].to;
				if(vis[t]) continue;
				q.push(t);
			}
		}
		printf("%d\n",Ans);
		for(int i=0;i<ss;i++){
			printf("%d",ans[i]);
			if(i!=ss-1) printf(" ");
		}
		if(t!=0) printf("\n"); 
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43179892/article/details/89683995