-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathunion_find.h
89 lines (71 loc) · 1.59 KB
/
union_find.h
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#ifndef UNION_FIND_H
#define UNION_FIND_H
#include "array_id_func.h"
#include <cassert>
//! An id-id-function that maps a node onto its components representative
struct UnionFind{
public:
UnionFind():node_count_(0){}
explicit UnionFind(int node_count):parent_(node_count), node_count_(node_count), component_count_(node_count){
parent_.fill(-1);
}
void reset(){
parent_.fill(-1);
component_count_ = node_count_;
}
int preimage_count()const{return node_count_;}
int image_count()const{return node_count_;}
void unite(int l, int r){
assert(0 <= l && l < node_count_);
assert(0 <= r && r < node_count_);
l = operator()(l);
r = operator()(r);
if(l != r){
--component_count_;
if(-parent_[l] < -parent_[r]){
parent_[r] += parent_[l];
parent_[l] = r;
}else{
parent_[l] += parent_[r];
parent_[r] = l;
}
}
}
int operator()(int x)const{
assert(0 <= x && x < node_count_);
if(is_representative(x))
return x;
int y = x;
while(!is_representative(y))
y = parent_[y];
int z = x;
while(!is_representative(z)){
int tmp = parent_[z];
parent_[z] = y;
z = tmp;
}
return y;
}
bool in_same(int x, int y)const{
return (*this)(x) == (*this)(y);
}
bool is_representative(int v)const{
assert(0 <= v && v < node_count_);
return parent_(v) < 0;
}
int component_size(int v)const{
assert(0 <= v && v < node_count_);
if(is_representative(v))
return -parent_(v);
else
return 0;
}
int component_count()const{
return component_count_;
}
private:
mutable ArrayIDFunc<int>parent_;
int node_count_;
int component_count_;
};
#endif