ac_library/dsu.rs
1//! A Disjoint set union (DSU) with union by size and path compression.
2
3/// A Disjoint set union (DSU) with union by size and path compression.
4///
5/// See: [Zvi Galil and Giuseppe F. Italiano, Data structures and algorithms for disjoint set union problems](https://core.ac.uk/download/pdf/161439519.pdf)
6///
7/// In the following documentation, let $n$ be the size of the DSU.
8///
9/// # Example
10///
11/// ```
12/// use ac_library::Dsu;
13/// use proconio::{input, source::once::OnceSource};
14///
15/// input! {
16/// from OnceSource::from(
17/// "5\n\
18/// 3\n\
19/// 0 1\n\
20/// 2 3\n\
21/// 3 4\n",
22/// ),
23/// n: usize,
24/// abs: [(usize, usize)],
25/// }
26///
27/// let mut dsu = Dsu::new(n);
28/// for (a, b) in abs {
29/// dsu.merge(a, b);
30/// }
31///
32/// assert!(dsu.same(0, 1));
33/// assert!(!dsu.same(1, 2));
34/// assert!(dsu.same(2, 4));
35///
36/// assert_eq!(
37/// dsu.groups()
38/// .into_iter()
39/// .map(|mut group| {
40/// group.sort_unstable();
41/// group
42/// })
43/// .collect::<Vec<_>>(),
44/// [&[0, 1][..], &[2, 3, 4][..]],
45/// );
46/// ```
47#[derive(Clone, Debug)]
48pub struct Dsu {
49 n: usize,
50 // root node: -1 * component size
51 // otherwise: parent
52 parent_or_size: Vec<i32>,
53}
54
55impl Dsu {
56 /// Creates a new `Dsu`.
57 ///
58 /// # Constraints
59 ///
60 /// - $0 \leq n \leq 10^8$
61 ///
62 /// # Complexity
63 ///
64 /// - $O(n)$
65 pub fn new(size: usize) -> Self {
66 Self {
67 n: size,
68 parent_or_size: vec![-1; size],
69 }
70 }
71
72 // `\textsc` does not work in KaTeX
73 /// Performs the Uɴɪᴏɴ operation.
74 ///
75 /// # Constraints
76 ///
77 /// - $0 \leq a < n$
78 /// - $0 \leq b < n$
79 ///
80 /// # Panics
81 ///
82 /// Panics if the above constraints are not satisfied.
83 ///
84 /// # Complexity
85 ///
86 /// - $O(\alpha(n))$ amortized
87 pub fn merge(&mut self, a: usize, b: usize) -> usize {
88 assert!(a < self.n);
89 assert!(b < self.n);
90 let (mut x, mut y) = (self.leader(a), self.leader(b));
91 if x == y {
92 return x;
93 }
94 if -self.parent_or_size[x] < -self.parent_or_size[y] {
95 std::mem::swap(&mut x, &mut y);
96 }
97 self.parent_or_size[x] += self.parent_or_size[y];
98 self.parent_or_size[y] = x as i32;
99 x
100 }
101
102 /// Returns whether the vertices $a$ and $b$ are in the same connected component.
103 ///
104 /// # Constraints
105 ///
106 /// - $0 \leq a < n$
107 /// - $0 \leq b < n$
108 ///
109 /// # Panics
110 ///
111 /// Panics if the above constraint is not satisfied.
112 ///
113 /// # Complexity
114 ///
115 /// - $O(\alpha(n))$ amortized
116 pub fn same(&mut self, a: usize, b: usize) -> bool {
117 assert!(a < self.n);
118 assert!(b < self.n);
119 self.leader(a) == self.leader(b)
120 }
121
122 /// Performs the Fɪɴᴅ operation.
123 ///
124 /// # Constraints
125 ///
126 /// - $0 \leq a < n$
127 ///
128 /// # Panics
129 ///
130 /// Panics if the above constraint is not satisfied.
131 ///
132 /// # Complexity
133 ///
134 /// - $O(\alpha(n))$ amortized
135 pub fn leader(&mut self, a: usize) -> usize {
136 assert!(a < self.n);
137 self._leader(a)
138 }
139
140 /// Returns the size of the connected component that contains the vertex $a$.
141 ///
142 /// # Constraints
143 ///
144 /// - $0 \leq a < n$
145 ///
146 /// # Panics
147 ///
148 /// Panics if the above constraint is not satisfied.
149 ///
150 /// # Complexity
151 ///
152 /// - $O(\alpha(n))$ amortized
153 pub fn size(&mut self, a: usize) -> usize {
154 assert!(a < self.n);
155 let x = self.leader(a);
156 -self.parent_or_size[x] as usize
157 }
158
159 /// Divides the graph into connected components.
160 ///
161 /// The result may not be ordered.
162 ///
163 /// # Complexity
164 ///
165 /// - $O(n)$
166 pub fn groups(&mut self) -> Vec<Vec<usize>> {
167 let mut leader_buf = vec![0; self.n];
168 let mut group_size = vec![0; self.n];
169 for i in 0..self.n {
170 leader_buf[i] = self.leader(i);
171 group_size[leader_buf[i]] += 1;
172 }
173 let mut result = vec![Vec::new(); self.n];
174 for i in 0..self.n {
175 result[i].reserve(group_size[i]);
176 }
177 for i in 0..self.n {
178 result[leader_buf[i]].push(i);
179 }
180 result
181 .into_iter()
182 .filter(|x| !x.is_empty())
183 .collect::<Vec<Vec<usize>>>()
184 }
185
186 fn _leader(&mut self, a: usize) -> usize {
187 if self.parent_or_size[a] < 0 {
188 return a;
189 }
190 self.parent_or_size[a] = self._leader(self.parent_or_size[a] as usize) as i32;
191 self.parent_or_size[a] as usize
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 #[test]
200 fn dsu_works() {
201 let mut d = Dsu::new(4);
202 d.merge(0, 1);
203 assert!(d.same(0, 1));
204 d.merge(1, 2);
205 assert!(d.same(0, 2));
206 assert_eq!(d.size(0), 3);
207 assert!(!d.same(0, 3));
208 assert_eq!(d.groups(), vec![vec![0, 1, 2], vec![3]]);
209 }
210}