题目链接
显然我们需要保存所有的点集,判断是否需要遍历所有的点就是看它本身是否是祖先节点。如果不是每次遍历该集合的连接点然后合并集合外的元素,合并之后既可以清空
启发式合并
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=8e5+10;
vector<int> q[maxn];
int f[maxn];
int Find(int x){
return f[x]==x?x:f[x]=Find(f[x]);
}
void Union(vector<int> &x,vector<int> &y){
if(x.size()<y.size()) swap(x,y);
for(auto i: y) x.push_back(i);
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
//ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t,n,m,x,T;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
f[i]=i;
q[i].clear();
}
for(int i=0,u,v;i<m;i++){
scanf("%d%d",&u,&v);
q[u].pb(v),q[v].pb(u);
}
scanf("%d",&T);
while(T--){
scanf("%d",&x);
if(Find(x)!=x) continue;
vector<int> cur=q[x];
q[x].clear();
for(auto i: cur){
int fi=Find(i);
if(fi!=x){
f[fi]=x;
Union(q[x],q[fi]);
q[fi].clear();
}
}
}
for(int i=0;i<n;i++) printf("%d%c",Find(i),i==n-1?'\n':' ');
}
return 0;
}
list
因为 l i s t list list是 S T L STL STL维护的双向链表,所有此题用 l i s t list list操作会更少,只是好像没有启发式合并快
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=8e5+10;
list<int> q[maxn];
int f[maxn];
int Find(int x){
return f[x]==x?x:f[x]=Find(f[x]);
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
//ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t,n,m,x,T;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
f[i]=i;
q[i].clear();
}
for(int i=0,u,v;i<m;i++){
scanf("%d%d",&u,&v);
q[u].pb(v),q[v].pb(u);
}
scanf("%d",&T);
while(T--){
scanf("%d",&x);
if(Find(x)!=x) continue;
list<int> cur=q[x];
q[x].clear();
for(auto i: cur){
int fi=Find(i);
if(fi!=x){
f[fi]=x;
q[x].splice(q[x].end(),q[fi]);
q[fi].clear();
}
}
}
for(int i=0;i<n;i++) printf("%d%c",Find(i),i==n-1?'\n':' ');
}
return 0;
}