J - Welcome Party(2019浙江省省赛)(bfs+优先队列)

J - Welcome Party(2019浙江省省赛)(bfs+优先队列)

Time Limit: 2000 ms
Memory Limit: 131072 KB
judge:
ZOJ
vjudge

Description

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 n n n participants of the World Finals, numbered from 1 1 1 to n n n 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 m m m 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 a a a and b b b are friends, and if participant b b b and c c c are friends, it’s NOT necessary that participant a a a and c c c are friends.

Input

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

The first line contains two integers n n n and m m m ( 1 ≤ n , m ≤ 1 0 6 1 \le n,m \le 10^6 1n,m106), the number of participants and the number of friendship relations.

The following m m m lines each contains two integers a a a and b b b ( 1 ≤ a , b ≤ n , a ≠ b 1 \le a,b \le n, a \neq b 1a,bn,a=b), indicating that the a a a-th and the b b b-th participant are friends. Each friendship pair is only described once in the input.

It is guaranteed that neither the sum of n n n nor the sum of m m m of all cases will exceed 1 0 6 10^6 106.

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 1 1 1 to n n n separated by a space, indicating the lexicographically smallest ordering of participants entering the hall that achieves this minimum number.

Consider two orderings P = p 1 , p 2 , … , p n P = p_1, p_2, \dots, p_n P=p1,p2,,pn and Q = q 1 , q 2 , … , q n Q = q_1, q_2, \dots, q_n Q=q1,q2,,qn, we say P P P is lexicographically smaller than Q Q Q, if there exists an integer k k k ( 1 ≤ k ≤ n 1 \le k \le n 1kn), such that p i = q i p_i = q_i pi=qi holds for all 1 ≤ i < k 1 \le i < k 1i<k, and p k < q k p_k < q_k pk<qk.

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个人要去参加聚会,但是场馆只有一个入口,且每次只能进一个人,即不能多个人同时进入。

当有人进入场馆发现里面没有自己的朋友时,这个人就会感到很失落,告诉你关系网,让你通过安排人们进入的顺序来使失落的人最少。如果有多个顺序都满足最佳答案,请输出字典序最小的那个。

题解

因为关系是双向的,所以人们会以一个一个的群组形式存在。那么当群组内有一个人进入场馆之后,群组内的其他人就不会感到失落了。所以感到失落的人数最小就是群组的个数。

维护一个优先队列,把已经进入场馆的人的朋友加入优先队列,每次取编号最小的那个,取了之后把他的朋友再加入优先队列,循环直到优先队列空。初始时把每一个群组的最小编号的人加入优先队列。

代码

#include <bits/stdc++.h>
#define maxn 1000005
#define _for(i, a) for(int i = 0; i < (a); ++i)
#define _rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define sc(x) scanf("%d", &x)
using namespace std;

int T, n, m, vis[maxn], used[maxn], ansnum;
priority_queue<int, vector<int>, greater<int> > pq;
vector<int> G[maxn], ans;  //邻接表

void init() {
    
    
	ansnum = 0;
	ans.clear();
	while (pq.size()) pq.pop();
	_rep(i, 1, n) vis[i] = 0, G[i].clear(), used[i] = 0;
}

void bfs(int S) {
    
    
	vector<int> vi;  //群组
	queue<int> que;
	que.push(S);
	vis[S] = 1;
	while (que.size()) {
    
    
		int c = que.front();
		que.pop();
		vi.push_back(c);
		_for(i, G[c].size()) {
    
    
			if (!vis[G[c][i]]) {
    
    
				que.push(G[c][i]);
				vis[G[c][i]] = 1;    //标记为已经分过群组
			}
		}
	}
	int _min = 0;
	for (int i = 1; i < vi.size(); ++i) {
    
    
		if (vi[i] < vi[_min]) _min = i;
	}
	pq.push(vi[_min]);   //把每个群组里编号最小的人加入优先队列
	used[vi[_min]] = 1;  //标记为已经在优先队列中
	ansnum++;            //群组数++
}

void sol() {
    
    
	init();
	_for(i, m) {
    
    
		int a, b;
		sc(a), sc(b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	_rep(i, 1, n) if (!vis[i]) bfs(i);
	while (pq.size()) {
    
    
		int c = pq.top();
		ans.push_back(c);
		pq.pop();
		_for(i, G[c].size()) {
    
    
			if (!used[G[c][i]]) pq.push(G[c][i]), used[G[c][i]] = 1;
		}
	}
}

int main() {
    
    
	while (cin >> T) {
    
    
		_for(i, T) {
    
    
			sc(n), sc(m);
			sol();
			printf("%d\n", ansnum);
			_for(i, n) printf("%d%s", ans[i], i == n - 1 ? "\n" : " ");
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42856843/article/details/105640648