ZOJ 4109 Welcome Party 並查集+優先隊列+bfs

Welcome Party
Time Limit: 2 Seconds       Memory Limit: 131072 KB

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.app

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.less

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.ide

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

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:this

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

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.code

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

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.blog

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 我的 m 個好友關係,讓這n我的按照必定的順序進入房間,若是一我的進入房間時,房間裏沒有他的朋友,那他就不開心。

  第一行輸出這n我的最小的不開心和,第二行輸出最小不開心和對應的順序,若是有多種順序,就輸出字典序最小的順序。

 

好友關係會把圖劃分紅多個聯通塊,對於一個聯通塊內部而言,不論誰第一個進,他自身都不開心,而此時再讓他的朋友進就沒問題。

因此一個聯通塊的最小不開心是 1。而聯通塊相互之間不影響,因此最小的不開心和就是聯通塊的數量。

至於如何找到字典序最小的方案,使用優先隊列來廣搜就行了,一個聯通塊內第一個被壓入隊列的點應該是字典序最小的點,可使用並查集來處理聯通塊的數量和塊內最小的點。

 

 

#include<cstdio> #include<cstring> #include<vector> #include<queue> #include<algorithm>
using namespace std; const int maxn = 1e6+5; int pre[maxn]; bool vis[maxn]; int ans[maxn]; int tmp; int n, m; vector<int>V[maxn]; void init(){ tmp = 0; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) pre[i] = i,V[i].clear(); } int find(int x){ int son = x,tmp; while(x!=pre[x]) x = pre[x]; while(son!=x){ tmp = pre[son]; pre[son] = x; son = tmp; } return x; } void add(int x,int y){ int u = find(x); int v = find(y); if(u<v)pre[v] = u; else pre[u] = v; } priority_queue<int,vector<int>,greater<int> >Q; void bfs(){ while(!Q.empty()){ int t = Q.top();Q.pop(); ans[tmp++] = t; for(int i=0;i<V[t].size();i++){ if(vis[V[t][i]]==0){ vis[V[t][i]] = 1; Q.push(V[t][i]); } } } } int main(){ int t, x, y; scanf("%d",&t); while(t--){ while(!Q.empty())Q.pop(); scanf("%d%d",&n,&m); init(); for(int i=0;i<m;i++){ scanf("%d%d",&x,&y); V[x].push_back(y);V[y].push_back(x); add(x,y); } for(int i=1;i<=n;i++) if(i==pre[i]) Q.push(i),vis[i]=1; printf("%d\n",Q.size()); bfs(); for(int i=0;i<tmp;i++) printf("%d%c",ans[i]," \n"[i==tmp-1]); } return 0; }
View Code
相關文章
相關標籤/搜索