1
1
/// Union Find はグラフの連結成分を管理します。
2
+ #[ derive( Clone , Debug ) ]
2
3
pub struct UnionFind {
3
- par : Vec < usize > ,
4
- size : Vec < usize > ,
4
+ nodes : Vec < NodeKind > ,
5
+ groups : usize ,
6
+ }
7
+
8
+ #[ derive( Clone , Copy , Debug ) ]
9
+ enum NodeKind {
10
+ Root { size : usize } ,
11
+ Child { parent : usize } ,
5
12
}
6
13
7
14
impl UnionFind {
8
- /// グラフの頂点数 `n` を渡します 。
9
- pub fn new ( n : usize ) -> UnionFind {
10
- UnionFind {
11
- par : ( 0 ..n ) . collect ( ) ,
12
- size : vec ! [ 1 ; n ] ,
15
+ /// 頂点数を `n` として初期化します 。
16
+ pub fn new ( n : usize ) -> Self {
17
+ Self {
18
+ nodes : vec ! [ NodeKind :: Root { size : 1 } ; n ] ,
19
+ groups : n ,
13
20
}
14
21
}
22
+
15
23
/// 頂点 `i` の属する連結成分の代表元を返します。
16
24
///
17
25
/// # Examples
26
+ ///
18
27
/// ```
19
28
/// use union_find::UnionFind;
20
29
/// let mut uf = UnionFind::new(6);
21
30
/// uf.unite(0, 1);
22
31
/// uf.unite(1, 2);
23
32
/// uf.unite(3, 4);
24
- /// let mut leaders = (0..6).map(|i| uf.find(i)).collect::<Vec<_>>();
25
- /// assert_eq!(leaders[0], leaders[0]);
26
- /// assert_eq!(leaders[0], leaders[1]);
27
- /// assert_eq!(leaders[1], leaders[2]);
28
- /// assert_eq!(leaders[0], leaders[2]);
29
- /// assert_eq!(leaders[3], leaders[4]);
30
- /// assert_ne!(leaders[0], leaders[3]);
31
- /// assert_ne!(leaders[0], leaders[5]);
33
+ ///
34
+ /// // [(0, 1, 2), (3, 4), (5)]
35
+ /// assert_eq!(uf.find(0), uf.find(0));
36
+ /// assert_eq!(uf.find(0), uf.find(1));
37
+ /// assert_eq!(uf.find(1), uf.find(2));
38
+ /// assert_eq!(uf.find(0), uf.find(2));
39
+ /// assert_eq!(uf.find(3), uf.find(4));
40
+ ///
41
+ /// assert_ne!(uf.find(0), uf.find(3));
42
+ /// assert_ne!(uf.find(0), uf.find(5));
32
43
/// ```
33
44
pub fn find ( & mut self , i : usize ) -> usize {
34
- if self . par [ i] != i {
35
- self . par [ i] = self . find ( self . par [ i] ) ;
45
+ assert ! ( i < self . nodes. len( ) ) ;
46
+
47
+ match self . nodes [ i] {
48
+ NodeKind :: Root { .. } => i,
49
+ NodeKind :: Child { parent } => {
50
+ let root = self . find ( parent) ;
51
+ if root == parent {
52
+ // noop
53
+ } else {
54
+ // 経路圧縮
55
+ self . nodes [ i] = NodeKind :: Child { parent : root } ;
56
+ }
57
+ root
58
+ }
36
59
}
37
- self . par [ i]
38
60
}
61
+
39
62
/// 頂点 `i` の属する連結成分と頂点 `j` の属する連結成分をつなげます。
40
- pub fn unite ( & mut self , i : usize , j : usize ) {
63
+ ///
64
+ /// 呼び出し前に別の連結成分だった場合 true を、同じ連結成分だった場合 false を返します。
65
+ ///
66
+ /// # Examples
67
+ ///
68
+ /// ```
69
+ /// use union_find::UnionFind;
70
+ /// let mut uf = UnionFind::new(6);
71
+ /// assert!(uf.unite(0, 1));
72
+ /// assert!(uf.unite(1, 2));
73
+ /// assert!(uf.unite(3, 4));
74
+ ///
75
+ /// // [(0, 1, 2), (3, 4), (5)]
76
+ /// assert!(!uf.unite(0, 2));
77
+ /// assert!(!uf.unite(3, 3));
78
+ ///
79
+ /// assert!(uf.unite(4, 5));
80
+ /// ```
81
+ pub fn unite ( & mut self , i : usize , j : usize ) -> bool {
41
82
let i = self . find ( i) ;
42
83
let j = self . find ( j) ;
43
84
if i == j {
44
- return ;
85
+ return false ;
45
86
}
46
- let ( i, j) = if self . size [ i] >= self . size [ j] {
47
- ( i, j)
48
- } else {
49
- ( j, i)
50
- } ;
51
- self . par [ j] = i;
52
- self . size [ i] += self . size [ j] ;
87
+
88
+ match ( self . nodes [ i] , self . nodes [ j] ) {
89
+ ( NodeKind :: Root { size : i_size } , NodeKind :: Root { size : j_size } ) => {
90
+ let total = i_size + j_size;
91
+ // マージテク
92
+ if i_size >= j_size {
93
+ self . nodes [ j] = NodeKind :: Child { parent : i } ;
94
+ self . nodes [ i] = NodeKind :: Root { size : total } ;
95
+ } else {
96
+ self . nodes [ i] = NodeKind :: Child { parent : j } ;
97
+ self . nodes [ j] = NodeKind :: Root { size : total } ;
98
+ }
99
+ }
100
+ _ => unreachable ! ( ) ,
101
+ }
102
+
103
+ self . groups -= 1 ;
104
+ true
53
105
}
106
+
54
107
/// 頂点 `i` の属する連結成分のサイズ (頂点数) を返します。
55
108
///
56
109
/// # Examples
110
+ ///
57
111
/// ```
58
112
/// use union_find::UnionFind;
59
113
/// let mut uf = UnionFind::new(6);
60
114
/// uf.unite(0, 1);
61
115
/// uf.unite(1, 2);
62
116
/// uf.unite(3, 4);
63
- /// assert_eq!(uf.get_size(0), 3);
64
- /// assert_eq!(uf.get_size(1), 3);
65
- /// assert_eq!(uf.get_size(2), 3);
66
- /// assert_eq!(uf.get_size(3), 2);
67
- /// assert_eq!(uf.get_size(4), 2);
68
- /// assert_eq!(uf.get_size(5), 1);
117
+ ///
118
+ /// // [(0, 1, 2), (3, 4), (5)]
119
+ /// assert_eq!(uf.size(0), 3);
120
+ /// assert_eq!(uf.size(1), 3);
121
+ /// assert_eq!(uf.size(2), 3);
122
+ /// assert_eq!(uf.size(3), 2);
123
+ /// assert_eq!(uf.size(4), 2);
124
+ /// assert_eq!(uf.size(5), 1);
69
125
/// ```
70
- pub fn get_size ( & mut self , i : usize ) -> usize {
71
- let p = self . find ( i) ;
72
- self . size [ p]
126
+ pub fn size ( & mut self , i : usize ) -> usize {
127
+ let root = self . find ( i) ;
128
+ match self . nodes [ root] {
129
+ NodeKind :: Root { size } => size,
130
+ _ => unreachable ! ( ) ,
131
+ }
73
132
}
133
+
74
134
/// 頂点 `i` と頂点 `j` が同じ連結成分に属するかどうかを返します。
75
135
///
76
136
/// # Examples
137
+ ///
77
138
/// ```
78
139
/// use union_find::UnionFind;
79
140
/// let mut uf = UnionFind::new(6);
80
141
/// assert!(uf.same(0, 0));
81
142
/// assert!(uf.same(3, 3));
82
143
/// assert!(uf.same(5, 5));
144
+ ///
83
145
/// uf.unite(0, 1);
84
146
/// uf.unite(1, 2);
85
147
/// uf.unite(3, 4);
148
+ ///
149
+ /// // [(0, 1, 2), (3, 4), (5)]
86
150
/// assert!(uf.same(0, 1));
87
151
/// assert!(uf.same(1, 2));
88
152
/// assert!(uf.same(0, 2));
@@ -91,4 +155,22 @@ impl UnionFind {
91
155
pub fn same ( & mut self , i : usize , j : usize ) -> bool {
92
156
self . find ( i) == self . find ( j)
93
157
}
158
+
159
+ /// 連結成分数を返します。
160
+ ///
161
+ /// # Examples
162
+ ///
163
+ /// ```
164
+ /// use union_find::UnionFind;
165
+ /// let mut uf = UnionFind::new(6);
166
+ /// uf.unite(0, 1);
167
+ /// uf.unite(1, 2);
168
+ /// uf.unite(3, 4);
169
+ ///
170
+ /// // [(0, 1, 2), (3, 4), (5)]
171
+ /// assert_eq!(uf.count_groups(), 3);
172
+ /// ```
173
+ pub fn count_groups ( & self ) -> usize {
174
+ self . groups
175
+ }
94
176
}
0 commit comments