zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第三场)G-Operating on a Graph(并查集)

    题目链接

    题意就是给定初始的图,每个点初始都各自属于一个组。然后每一次操作给定一个数字(k),这次操作会将与组(k)中的任意一点相邻的点的对应组合并到组(k)中。最后求每个点的组编号。
    既然是分组,那么利用并查集应该是很明确的,注意到一旦合并之后那么这两个组的关系就永远相同了,就算是变化的话也是一起变化。那么具体操作起来的话每次组合并只要把所有相关点缩到祖先节点上,然后通过祖先节点与其余点根据原来的边情况进行重连就可以了。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=8e5+10;
    int pre[maxn];
    vector<int> edg[maxn];
    inline int find(int x){return x==pre[x]?x:pre[x]=find(pre[x]);}
    void merge(int n){
        vector<int> tmp=edg[n];
        edg[n].clear();
        for(int i : tmp){
            int k=find(i);
            if(k!=n){
                pre[k]=n;
                if(edg[n].size()<edg[k].size())swap(edg[n],edg[k]);
                for(auto v:edg[k]){
                    edg[n].push_back(v);
                }
                edg[k].clear();
            }
        }
    }
    int main(){
        int t;cin>>t;
        while(t--){
            int n,m;
            cin>>n>>m;
            for(int i=0;i<n;i++){
                pre[i]=i;
                edg[i].clear();
            }
            for(int i=0,u,v;i<m;i++){
                cin>>u>>v;
                edg[u].push_back(v);
                edg[v].push_back(u);
            }
            int q;
            cin>>q;
            while(q--){
                int k;
                cin>>k;
                if(find(k)!=k)continue;
                merge(k);
            }
            for(int i=0;i<n;i++)cout<<find(i)<<" ";
            cout<<"
    ";
        }
        return 0;
    }
    
  • 相关阅读:
    33选6算法:M个数N个为一组,无重复的排列组合
    文件墙 CFilewall
    公司代码阅读笔记 记于 2013-09-23
    简单的同步MSMQ
    Markdown 使用说明
    Freezable 对象(WPF)
    AngularJS-入门篇
    第二节Unity3D开发环境安装(windows系统)
    第一节Unity3D简介
    数据库出现可疑解决办法
  • 原文地址:https://www.cnblogs.com/charles1999/p/13339434.html
Copyright © 2011-2022 走看看