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; }