【模板】并查集

find的递归实现,路径压缩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=10005;
int a[MAXN];

int find(int x){
if(x!=a[x])a[x]=find(a[x]);
return a[x];
}

inline void unite(int x,int y){
a[find(x)]=find(y);
}

int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
a[i]=i;
int x,y,z;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&z,&x,&y);
if(z==1)unite(x,y);
else
if(find(x)==find(y))printf("Y\n");
else printf("N\n");
}
return 0;
}

另外,find操作的非递归写法,不过效率差别不大
这里要注意一点,find函数里的t数组一定不要初始化。因为不初始化是常数级,初始化是n级的,相差很大。

1
2
3
4
5
6
7
8
9
10
inline int find(int x){
int k,i,t[MAXN];
for(k=1;a[x]!=x;k++){
t[k]=x;
x=a[x];
}
for(i=1;i<=k-1;i++)
a[t[i]]=x;
return x;
}

又尝试了C++面向对象实现(

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include<iostream>
#include<cstdio>
#include<malloc.h>
using namespace std;

struct node{
int father;
int data;
};

class union_find{
public:
void init(int max){
set=(struct node *)malloc(sizeof(struct node)*max);
t=(int *)malloc(sizeof(int)*max);
for(int i=0;i<max;i++){
set[i].father=i;
set[i].data=i;
}
}

int find(int x){
int k=0,i;
while(set[x].father!=x){
k++;
t[k]=x;
x=set[x].father;
}
for(i=1;i<=k-1;i++)
set[t[i]].father=x;
return x;
}

void unite(int x,int y){
set[find(x)].father=find(y);
}

bool same_set(int x,int y){
return find(x)==find(y);
}

void dispose(){
free(set);
free(t);
}

private:
int *t;
struct node *set;
};

int main(){
int n,m;
scanf("%d%d",&n,&m);
int zi,xi,yi;
int i;
union_find a;
a.init(10005);

for(i=1;i<=m;i++){
scanf("%d%d%d",&zi,&xi,&yi);
if(zi==1){
a.unite(xi,yi);
}
else if(zi==2){
if(a.same_set(xi,yi))printf("Y\n");
else printf("N\n");
}
}
return 0;
}