Welcome Party(ZOJ-4109)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011815404/article/details/89607857

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

Input

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

The first line contains two integers n and m (1<=n,m<=10^6), the number of participants and the number of friendship relations.

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

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

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 P=p1,p2,...,pn and Q=q1,q2,..,qn, we say P is lexicographically smaller than Q, if there exists an integer  k(1<=k<=n), such that  holds for all pi=qi,1<=i<k and 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

题意:t 组数据,每组给出 n 个人 m 个认识关系,现在 n 个人要进入一个区域,如果第 i 个人进入这个区域时没有他认识的人的话,不高兴度就 +1,问最少的不高兴度是多少,并将进入顺序按字典序输出

思路:

首先认识关系是双向的,其次根据题意可知,不高兴度就是图中关系块的块数,每个块只要让一个人不开心,剩下的人都可以通过关系逐个进屋,因此首先使用并查集判断分块,在这个过程中选择下标最小的人让他成为最早进屋的,以此决定字典序

此后使用优先队列,每次选择让编号最小的进屋,然后将其朋友加入队列,再选择最小的,直到队列为空

Source Program

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 2000000+5;
const int dx[] = {0,0,-1,1,-1,-1,1,1};
const int dy[] = {-1,1,0,0,-1,1,-1,1};
using namespace std;

struct Edge {
    int to,next;
} edge[N*3];
int n,m;
int tot,head[N],father[N];
bool vis[N];
int res;

void addEdge(int x,int y) {
    edge[++tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;

}
int Find(int x) {
    if(x==father[x])
        return x;
    return father[x]=Find(father[x]);
}
void Union(int x,int y) {
    x=Find(x);
    y=Find(y);
    if(x!=y) {
        res--;
        if(x<y)
            father[y]=x;
        else
            father[x]=y;
    }
}

priority_queue<int,vector<int>, greater<int> >Q;
void dfs() {
    int cnt=0;
    while(!Q.empty()) {
        int x=Q.top();
        Q.pop();

        cnt++;
        if(cnt==n)
            printf("%d\n",x);
        else
            printf("%d ",x);

        for(int i=head[x]; i!=-1; i=edge[i].next) {
            int y=edge[i].to;
            if(vis[y])
                continue;
            else {
                vis[y]=true;
                Q.push(y);
            }
        }
    }
}
int main() {
    int t;
    scanf("%d",&t);
    while(t--) {
        tot=0;

        memset(vis,false,sizeof(vis));
        memset(head,-1,sizeof(head));
        while(!Q.empty())
            Q.pop();

        scanf("%d%d",&n,&m);
        res=n;
        for(int i=1; i<=n; i++)
            father[i]=i;
        while(m--){
            int x,y;
            scanf("%d%d",&x,&y);
            addEdge(x,y);
            Union(x,y);
            Union(y,x);
        }
        printf("%d\n",res);//连通块个数

        for(int i=1; i<=n; i++) {
            if(vis[Find(i)]==0) {//选择字典序最小的入队
                vis[Find(i)]=1;
                Q.push(Find(i));
            }
        }
        dfs();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u011815404/article/details/89607857
今日推荐