zoukankan      html  css  js  c++  java
  • 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.

    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

     题意: 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
    ",Q.size());
            bfs();
            for(int i=0;i<tmp;i++)
                printf("%d%c",ans[i]," 
    "[i==tmp-1]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    数据结构与算法(C++)之swap交换
    常用shell脚本
    Java知识库
    jenkins:你们是怎么在控制台实时打印服务启动日志的?
    mqtt压力测试工具emqtt
    postman中获取环境变量和全局变量
    不想当将军的士兵不是好士兵吗?
    永久关闭火狐浏览器自动更新的方法
    性能测试案例:线程池拒绝策略使用不当导致并发一上去就会出现大量报错
    性能测试案例:一个频繁fgc问题
  • 原文地址:https://www.cnblogs.com/kongbb/p/10806073.html
Copyright © 2011-2022 走看看