题意:
n个点m条边的图
数据范围:n,m<=8e5
解法:
颜色变动用并查集合并,
vector(x)维护与x相邻的点,相邻点维护可以启发式暴力合并vector(似乎可以用链表)
ps:
如果不启发式合并,我的代码会MLE
也可以用链式前向星存图,多记录一个tail,链表的合并很快
题解:
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=8e5+5;
vector<int>g[maxm];
int pre[maxm];
int n,m;
int ffind(int x){
return pre[x]==x?x:pre[x]=ffind(pre[x]);
}
signed main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
//init
for(int i=0;i<n;i++){
pre[i]=i;
g[i].clear();
}
//
for(int i=1;i<=m;i++){
int a,b;scanf("%d%d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
}
int q;scanf("%d",&q);
while(q--){
int x;scanf("%d",&x);
if(pre[x]!=x)continue;
vector<int>temp;
for(int v:g[x]){
int rt=ffind(v);
if(rt!=x){
//merged
if(temp.size()<g[rt].size()){//启发式合并
swap(temp,g[rt]);
}
for(auto i:g[rt]){//暴力
temp.push_back(i);
}
g[rt].clear();
//
pre[rt]=x;
}
}
swap(g[x],temp);
}
for(int i=0;i<n;i++){
printf("%d ",ffind(i));
}
puts("");
}
return 0;
}