并查集很容易理解的一种数据结构,简单介绍一下拿着模版直接用即可。
用集合中的某个元素来代表这个集合,该元素称为集合的代表元
。
对于每一个元素 parent[x]指向x在树形结构上的父亲节点。如果x是根节点,则令parent[x] = x。
对于查找操作,假设需要确定x所在的的集合,也就是确定集合的代表元。可以沿着parent[x]不断在树形结构中向上移动,直到到达根节点。判断两个节点是否连通,只需要判断它们的祖先是否相同。
模版
void init(int n){
for(int i=1;i<=n;i++){
fa[i]=i;
}
}
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void unite(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx==fy)return;
else fa[fx]=fy;
}
应用
题源:hdu 1232
#include <vector>
#include <stdio.h>
#include <queue>
using namespace std;
const int maxn = 1e5+5;
int fa[maxn];
void init(int n){
for (int i = 1; i <= n; ++i)
fa[i] = i;
}
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void unite(int x, int y){
int fx = find(x);
int fy = find(y);
if(fx == fy) return ;
fa[fx] = fy;
}
void print(int n){
for (int i = 1; i <= n; ++i)
printf("%d ", fa[i]);
printf("\n");
}
int main(){
int M,N;
while(~scanf("%d",&N)&&N!=0&&~scanf("%d",&M)){
init(N);
for (int i = 1; i <= M; ++i){
int u, v;
scanf("%d%d", &u, &v);
unite(u, v);
}
int ans=0;
for(int i=1;i<=N;i++){
if(fa[i]==i){
ans++;
}
}
printf("%d\n",ans-1);
}
}