• ZOJ


    题目地址  

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

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

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

            使用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
    ",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
  • 相关阅读:
    Identifier expected after this token
    需要整理的
    Context
    SharedPreferences
    一些常规注意事项
    一个点亮屏幕的service
    BroadcastReceiver中调用Service
    BroadcastReceiver
    Service
    微服务简介
  • 原文地址:https://www.cnblogs.com/JiaaaaKe/p/11294477.html
Copyright © 2020-2023  润新知