ZOJ - 4109 Welcome Party(并查集+优先队列+vector)

ZOJ原题链接: 传送门

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~n的参赛选手要通过一个入口进入场馆,给出m行数据,每行两个编号代表a和b是朋友,参赛选手需要排队一个一个进入场馆,每当一个人到达场馆,如果里面有他的朋友存在,那么他就会开心,否则不开心,注意,如果a和b是朋友b和c是朋友,那么a和c不一定是朋友,在确保不开心人数最少的情况下,使得参赛者的进入序列中小的编号尽可能排在前面,输出最少的不开心的人数和此时最小的排队序列

题目分析

这是一道对基础知识的考验比较全面的题目,解题主要用到了(并查集,优先队列,vector向量方面的知识),首先通过并查集的方法将输入的数据转化成一个一个的朋友集合,同时记录下每个集合编号最小的那个人一定是这个集合中最先去排队入场的人,牺牲你一个幸福全村人,他们的和就是不开心的人数。那么自然而然就需要一个能将这些必定要牺牲的人存放进去的容器(队列),而且可以每次取出编号最小的那个人,尽管都是要牺牲的,编号最小的还是要最先牺牲呀,那么优先队列的优势就体现出来了,每个放入的编号都能按我们的要求从小到大排序,这正是我们需要的。对于每个取出来去排队的人,我们要遍历与他直接相连的朋友的编号,如果没有加入到队列中,则加入,加入过了就跳过,这样做是因为有可能刚刚去排队的人有一位朋友他的编号比那些一定要牺牲的人编号还要小,那就先让他排进来,插到那些已经在队列中的人前面,反正他不会不开心,他的朋友这不刚刚进去了嘛,早点去排队正符合题意。那么我们此时就需要一个能记录一对多关系的容器,把每个人的朋友都和具体的每个人联系起来,vector正符合我们的需要。最后就是把不开心的人数输出,把排队的序列输出,over~

本题代码

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;

const int N=1000005;
int vis[N];
int root[N];
int arr[N];
vector<int> p[N];

int find(int x){
    while(root[x]!=x) x=root[x];
    return x;
}
void Union(int x,int y){
    int fx=find(x);
    int fy=find(y);
    if(fx<fy) root[fy]=fx;
    else root[fx]=fy;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        priority_queue<int, vector<int>, greater<int> >q;
//      while(!q.empty()) q.pop();
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<=n;i++){  //初始化工作 
            root[i]=i;
            vis[i]=0;
            p[i].clear();
        } 
        int x,y;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            Union(x,y);         //并查集只是为了找出每个集合最小的点作为根节点,其连接方式并不重要 
            p[x].push_back(y);  //此处要注意编号大的人可以拥有编号小的作为朋友 
            p[y].push_back(x);  //编号小的也可以拥有编号大的作为朋友 
        }
        int cnt=0;
        for(int i=1;i<=n;i++){
            if(root[i]==i){
                q.push(i);      //将每个集合编号最小的根放入队列 
                cnt++;          //这些人包括那些没有任何朋友的人 
            } 
        }   
        int point=0;
        while(!q.empty()){
            int x=q.top();
            q.pop();
            if(vis[x]==0){//原先代码中没有判断这句话造成重复加点的情况产生 
                vis[x]=1;
                arr[++point]=x;
                for(int i=0;i<p[x].size();i++){//遍历下标为r.x的向量的每一个元素          
                    if(vis[p[x][i]]==0) q.push(p[x][i]);    //如果这个朋友没有在之前就被排入队列则将它放入优先队列 
                } 
            }   
        }
        printf("%d\n",cnt);
        for(int i=1;i<=point;i++){
            if(i!=1) printf(" ");
            printf("%d",arr[i]);
        }
        printf("\n");
    }
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容