2019 浙江省赛 zoj 4109 Welcome Party 并查集+优先队列+bfs

                                   Welcome Party

Time Limit: 2000 msMemory 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

题目大意:就是一群人进入会场,这些人之间有朋友关系,并且朋友关系不能传递。每次当一个人进入会场时,如果里面没有他的朋友,就会不开心,求最少的不开心人数,并且按字典序最小输出。

思路:既然进去没有朋友会不开心,所以并查集求联通块,每个连通块肯定会有一个人不开心,然后就是谁先进的问题了,很容易想到用优先队列来实现bfs遍历,这样就能够保证每次进入的人是最优的。(注意,一开始的时候需要把每个连通块的祖先先压进优先队列,在并查集里稍作修改就能得到每个连通块的最小值)。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>

using namespace std;
const int Max = 1e6+10;
vector<int> v[Max];
int pre[Max];
bool vis[Max];
int point[Max];
int finds(int x)
{
	 /* int k, j, r;
    r = x;
    while(r != pre[r])    
        r = pre[r];     
    k = x;        
    while(k != r)       
    {
        j = pre[k];        
        pre[k] = r;     
        k = j;                    
    }
    return r;   */
    while(x!=pre[x])
    {
      x=pre[x];
    }
    return x;
}

void cheak(int x,int y)
{
    int fx = finds(x);
    int fy = finds(y);
    if(fx!=fy)
    {
        if(fy<fx)
            pre[fx] = fy;
        else
            pre[fy] = fx;
    }
}

void bfs(int x)
{
	int i;
    priority_queue<int,vector<int>,greater<int> > q;
    for(i=0; i<x; i++)
    {
        q.push(point[i]);
    }
    while(!q.empty())
    {
        int st = q.top();
        q.pop();
        vis[st] = true;
        if(st!=1)
            printf(" %d",st);
        else
            printf("%d",st);

        for(int i=0; i<v[st].size(); i++)
        {
            if(vis[v[st][i]]==false)
            {
                vis[v[st][i]]=true;
                q.push(v[st][i]);
            }
        }
    }

}
int main ()
{
    int t,i;
    int n,m,x,y;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=0; i<=n; i++)
            v[i].clear();
        for(i=1; i<=n; i++)
            pre[i] = i;
        memset(vis,false,sizeof(vis));
        for(int i=0; i<m; i++)
        {
            scanf("%d%d",&x,&y);
            v[x].push_back(y);
            v[y].push_back(x);
            cheak(x,y);
        }
        int s = 0;
        for(i=1; i<=n; i++)
        {
            if(pre[i]==i)
            {
                point[s++] = i;
            }
        }
        printf("%d\n",s);
        bfs(s);
        puts("");
    }
    return 0;
}

匪夷所思的是用路径压缩还比朴素要慢一点。。。。可能是测评鸡的问题??

发布了22 篇原创文章 · 获赞 4 · 访问量 539

猜你喜欢

转载自blog.csdn.net/yp0413170331/article/details/101393383