2020牛客多校赛第三场G题Operating on a Graph(并查集链表)

题目链接:https://ac.nowcoder.com/acm/contest/5668/G

题意:输入n点m边无向图,q次操作,每次操作讲qi向量的点归为一类,q次操作后,输出所以点属于那一类。

题解:并查集很好用,直接判断是否是同一类,如果不是,直接return,表示已经归为一类了,反之遍历与当前点相连的点与当前点并。归为一类的缩成一点,这里用链表,首先是自己一个点,并时后面加上儿子的链接。

最后输出要find一下,保证并查集更新彻底。

 

#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=8e5+7;
const ll mod =1e9+7;
int fa[maxn],vis[maxn];
int n,m;
int a[maxn];
int findfa(int x){
    if( fa[x]==x) return x;
    else return fa[x]=findfa(fa[x]);
}
vector<int> mp[maxn];
list<int> lk [maxn];
int main(){
    IOS
    int t,q;
    cin>>t;
    while(t--){
        cin>>n>>m;
        
        for(int i=0;i<n;i++){
            fa[i]=i;
            lk[i].clear();
            mp[i].clear();
            lk[i].push_back(i);
        }
        for(int i=0,x,y;i<m;i++){
            cin>>x>>y;
            mp[x].push_back(y);
            mp[y].push_back(x);
        }
        cin>>q;
        for(int i=0,op;i<q;i++){
            cin>>op;
            if(fa[op]!=op) continue;
            int res=lk[op].size();
            while(res--){
                int now=lk[op].front();
                lk[op].pop_front();
                for(int i=0;i<mp[now].size();i++){
                    int xx=findfa(mp[now][i]);
                    if(xx!=op){
                        fa[xx]=op;
                        lk[op].splice(lk[op].end(),lk[xx]); 
                    }
                }
            }
        }
        for(int i=0;i<n;i++)
            cout<<findfa(i)<<" ";
        cout<<endl;
    }
    
    
    return 0;
}

 

posted @ 2020-08-06 22:50  杰瑞与汤姆  阅读(147)  评论(0编辑  收藏  举报