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

题目地址  

题目大意:n个人,m种关系 (a和b是朋友),可以看作 n个点,m条边, 用图论的知识解题

                  问在使最少人不开心的情况下,输出进房间字典序排序最小的顺序。(如果在小A进房间之前房间内没有他的朋友,他就不开心)

                  使用并查集分块,每个并查集的根节点和独立点(无朋友)的总个数就是输出的不开心的人数。

        使用BFS和优先队列遍历存入的图,保证字典序最小。将路径存入答案数组。

代码:

ZOJ - 4109  -   Welcome Party (并查集 + BFS + 优先队列)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;

int s[maxn];
int vis[maxn];
vector<int> Edge[maxn];  //二维!
vector<int> sto;         //答案 

int Find(int t)
{
    return t==s[t]?t:s[t]=Find(s[t]);
}
void Merge(int st,int ed)
{
    int t1=Find(st);
    int t2=Find(ed);
    if(t1==t2) return;
    if(t1>t2)swap(t1,t2);
    s[t2]=t1;
}
void bfs(int root) 
{
    priority_queue<int,vector<int>,greater<int> > Q;  
    while(!Q.empty()) Q.pop();
    Q.push(root);
    vis[root] = 1;
    while(!Q.empty()) {
        int t = Q.top();
        Q.pop();
        sto.push_back(t);
    //    cout << " size = " << sto.size() << endl;
        for(int i = 0; i < Edge[t].size(); i++) {
            int temp = Edge[t][i];
            if(vis[temp]) continue;
            vis[temp] = 1;
            Q.push(temp);
        }
    }
}
int main()
{
    int T, n, m;
    cin >> T;
    while(T--) {
        int ans = 0;
        cin >> n >> m;
        sto.clear();      //清空答案数组!! 
        for(int i = 0; i <= n; i++) {    //从0开始,把所有根节点和无朋友的点存在Edge[0]里面 
            s[i] = i;                    //并查集数组 
            Edge[i].clear();             //存边(两点 
            vis[i] = 0;                  //标记数组 
        }
        for(int i = 1; i <= m; i++) {
            int x, y;
            cin >> x >> y;
            Edge[x].push_back(y);       //关系是相互的  所以在Merge时需要判断大小 
            Edge[y].push_back(x);
            Merge(x, y);
        }
        for(int i = 1; i <= n; i++) {
            if(s[i] == i) {             //所有的根节点 和 不存在边的点(无朋友的) 
                ans ++;
                Edge[0].push_back(i);
            }
        }
        bfs(0);
        printf("%d\n",ans);
        int len = sto.size();
        for(int i = 1; i < len-1; i++) {
            cout << sto[i] << " ";
        }
        cout << sto[len-1] << endl;
    }
    return 0;
}
View Code

 

上一篇:201871010107-公海瑜《面向对象程序设计(java)》第一周学习总结


下一篇:201871010116-祁英红《面向对象程序设计(java)》第一周学习总结