Operating on a Graph(并查集)
思路:并查集+链表。
但是我的这个写法没体现出链表的优势。主要思路就是将当前询问结点 的相邻结点进行访问,如果根不是 就进行合并结点,更新并查集。
貌似有一个优化就是先将 复制一份,然后清空,如果比当前子结点 的大小要小,就直接交换。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=8e5+10,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int n,m,q,s[N];
list<int>g[N];
int find(int x){
return x==s[x]?x:s[x]=find(s[x]);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(reg int i=0;i<n;i++) s[i]=i,g[i].clear();
for(reg int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v),g[v].push_back(u);
}
scanf("%d",&q);
while(q--){
int x;
scanf("%d",&x);
if(x!=find(x)) continue;
list<int>tmp=g[x];
g[x].clear();
for(auto j:tmp){
int u=find(j);
if(u!=x){
s[u]=x;
if(g[x].size()<g[u].size()) g[x].swap(g[u]);
for(auto v:g[u]){
g[x].push_back(v);
}
}
}
}
for(int i=0;i<n;i++) printf("%d ",find(i));
puts("");
}
return 0;
}