并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。
(来自百度百科)
并查集的操作主要有3个:
1,初始化:把每个点所在集合初始化为其自身。通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N)。
2,查找:查找元素所在的集合,即根节点。
3,合并:将两个元素所在的集合合并为一个集合。
贴模板代码
int cnt,pre[maxn],n;
void init(){
cnt=n; //n为节点数
for(int i=0;i<n;i++)
pre[i]=i;
}
int find(int p){
int root=p;
while(pre[root]!=root)
root=pre[root];
int temp;
while(pre[p]!=p){ // 尽可能简便地缩短树的高度
temp=pre[p];
pre[p]=root;
p=temp;
}
return root;
}
void connect(int x,int y){
int fx=find(x),fy=find(y);
if(fx!=fy){
pre[fx]=fy;
cnt--;
}
}
典型模板题:hdu 1232(求联通分支数)
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int n,m,pre[1005];
int find(int k){
int root=k;
while(pre[root]!=root)
root=pre[root];
int temp;
while(pre[k]!=k){
temp=pre[k];
pre[k]=root;
k=temp;
}
return root;
}
void connect(int x, int y){
int fx=find(x), fy=find(y);
if(fx!=fy){
pre[fx]=fy;
n--;
}
}
void init(){
for(int i=1;i<=n;i++){
pre[i]=i;
}
}
int main()
{
freopen("input.txt","r",stdin);
int a,b;
while(scanf("%d%d",&n,&m) && n){
init();
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
connect(a,b);
}
printf("%d\n",n-1);
}
return 0;
}