[并查集]Welcome Party

本文围绕ICPC 2020世界总决赛欢迎派对展开,因安检设备有限,仅设一个入口,一人一次进入。为减少不开心的参与者数量,需确定入场顺序。输入包含测试用例数、参与者数和友谊关系,输出最小不开心参与者数及入场顺序。正确解法是用并查集找块,用优先队列遍历。

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.

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.

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

正确解法:

用并查集,找出一共有几块,然后用优先队列遍历。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <algorithm>
  6 #include <set>
  7 #include <map>
  8 #include <queue>
  9 #include <vector>
 10 #include <cctype>
 11 #include <sstream>
 12 using namespace std;
 13 typedef long long ll;
 14 const int inf=0x7fffffff;
 15 const int N=1000000+100;
 16 const int M=50000+10;
 17 const int MOD=1e9+7;
 18 const double PI=acos(-1.0);
 19 int T,n,m;
 20 int Link[N],len=0,bok[N],fa[N];
 21  priority_queue <int,vector<int>,greater<int> > q;
 22 struct node
 23 {
 24     int y,next;
 25 }e[N*3];
 26 void insert(int xx,int yy)
 27 {
 28     e[++len].next=Link[xx];
 29     Link[xx]=len;
 30     e[len].y=yy;
 31 }
 32 int getf(int x)
 33 {
 34     if(fa[x]==x)    return x;
 35     fa[x]=getf(fa[x]);
 36     return fa[x];
 37 }
 38 void merge(int a,int b)
 39 {
 40     a=getf(a);  b=getf(b);
 41     if(a!=b)
 42     {
 43         if(a>b) fa[a]=b;
 44         else    fa[b]=a;
 45     }
 46 }
 47 int main()
 48 {
 49     scanf("%d",&T);
 50     while(T--)
 51     {
 52         for(int i=1;i<=n;i++)
 53         {
 54             e[i].y=e[i].next=0;
 55             Link[i]=0;
 56             bok[i]=0;
 57         }
 58         int xx,yy;
 59         scanf("%d %d",&n,&m);
 60         len=0;
 61         for(int i=1;i<=n;i++)
 62             fa[i]=i;
 63         while(m--)
 64         {
 65             scanf("%d %d",&xx,&yy);
 66             insert(xx,yy);
 67             insert(yy,xx);
 68             merge(xx,yy);
 69         }
 70         int ans=0;
 71         priority_queue <int,vector<int>,greater<int> > q;
 72         for(int i=1;i<=n;i++)
 73             if(fa[i]==i)
 74             {
 75                 bok[i]=1;
 76                 q.push(i);
 77                 ans++;
 78             }
 79         printf("%d\n",ans);
 80         int flag=0;
 81         while(!q.empty())
 82         {
 83             int kk=q.top();
 84             //cout<<kk<<endl;
 85             q.pop();
 86             if(flag==0)
 87             {
 88                 printf("%d",kk);
 89                 flag=1;
 90             }
 91             else
 92                 printf(" %d",kk);
 93             for(int i=Link[kk];i;i=e[i].next)
 94                 if(bok[e[i].y]==0)
 95                 {
 96                     bok[e[i].y]=1;
 97                     q.push(e[i].y);
 98                     //cout<<e[i].y<<endl;
 99                 }
100 
101         }
102         printf("\n");
103     }
104 
105     return 0;
106 }
View Code

 

转载于:https://www.cnblogs.com/Kaike/p/10881351.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值