incremental_tree_set_union/
static_tree.rs1use alloc::vec;
2use alloc::vec::Vec;
3
4use crate::answer_table::{AnswerTable, encode_forest};
5use crate::macroset::Macroset;
6use crate::microset::{Microset, NO_PARENT, NodeInfo, microfind};
7
8#[derive(Clone, Debug)]
22pub struct StaticTreeSetUnion {
23 node_info: Vec<NodeInfo>,
24 microsets: Vec<Microset>,
25 all_nodes: Vec<u32>,
28 answer_table: AnswerTable,
29 macroset: Macroset,
30 n: usize,
31}
32
33#[inline]
35fn csr_children<'a>(v: usize, offsets: &[u32], children: &'a [u32]) -> &'a [u32] {
36 &children[offsets[v] as usize..offsets[v + 1] as usize]
37}
38
39impl StaticTreeSetUnion {
40 pub fn from_parents(parents: &[usize]) -> Self {
43 let n = parents.len();
44 assert!(n >= 1, "tree must have at least one node");
45
46 let root = (0..n)
48 .find(|&i| parents[i] == i)
49 .expect("tree must have a root (parents[root] == root)");
50
51 let mut degree = vec![0u32; n];
54 for (i, &p) in parents.iter().enumerate() {
55 if i != root {
56 degree[p] += 1;
57 }
58 }
59 let mut offsets = vec![0u32; n + 1];
61 for i in 0..n {
62 offsets[i + 1] = offsets[i] + degree[i];
63 }
64 let num_edges = if n > 0 { n - 1 } else { 0 };
66 let mut children_flat = vec![0u32; num_edges];
67 let mut pos = offsets[..n].to_vec();
68 for (i, &p) in parents.iter().enumerate() {
69 if i != root {
70 children_flat[pos[p] as usize] = i as u32;
71 pos[p] += 1;
72 }
73 }
74
75 let mut levels = vec![0u32; n];
77 let mut queue = vec![root];
78 let mut qi = 0;
79 while qi < queue.len() {
80 let v = queue[qi];
81 qi += 1;
82 for &c in csr_children(v, &offsets, &children_flat) {
83 levels[c as usize] = levels[v] + 1;
84 queue.push(c as usize);
85 }
86 }
87
88 let answer_table = AnswerTable::new(n);
90 let b = answer_table.b;
91
92 let mut node_info = vec![NodeInfo::default(); n];
94 for (i, &p) in parents.iter().enumerate() {
95 node_info[i].parent = if i == root { NO_PARENT } else { p as u32 };
96 node_info[i].level = levels[i];
97 }
98
99 let mut assigned = vec![false; n];
101 let mut microsets_list: Vec<Microset> = Vec::new();
102 let mut all_nodes: Vec<u32> = Vec::with_capacity(n);
103 let mut d = vec![1u32; n];
104
105 let postorder = Self::postorder(root, &offsets, &children_flat);
107
108 let threshold_2x = b + 1;
110
111 for &v in &postorder {
112 d[v] = 1;
113 let mut child_idx = 0;
114 let child_list = csr_children(v, &offsets, &children_flat);
115
116 loop {
117 while 2 * d[v] < threshold_2x && child_idx < child_list.len() {
118 let w = child_list[child_idx] as usize;
119 d[v] += d[w];
120 child_idx += 1;
121 }
122
123 if 2 * d[v] < threshold_2x {
124 break;
125 }
126
127 debug_assert!(child_idx > 0);
128
129 let split_children = &child_list[..child_idx];
130 Self::add_microset(
131 v as u32,
132 split_children,
133 &offsets,
134 &children_flat,
135 &mut assigned,
136 &mut node_info,
137 &mut microsets_list,
138 &mut all_nodes,
139 );
140
141 d[v] = 1;
142 if child_idx >= child_list.len() {
143 break;
144 }
145 }
146 }
147
148 Self::add_final_microset(
150 root,
151 &offsets,
152 &children_flat,
153 &mut assigned,
154 &mut node_info,
155 &mut microsets_list,
156 &mut all_nodes,
157 );
158
159 let mut macroset = Macroset::new(n);
161 for ms in µsets_list {
162 if ms.root != NO_PARENT {
163 macroset.make_set(ms.root, node_info[ms.root as usize].level);
164 }
165 }
166
167 Self {
168 node_info,
169 microsets: microsets_list,
170 all_nodes,
171 answer_table,
172 macroset,
173 n,
174 }
175 }
176
177 fn postorder(root: usize, offsets: &[u32], children: &[u32]) -> Vec<usize> {
178 let mut result = Vec::new();
179 let mut stack: Vec<(usize, bool)> = vec![(root, false)];
180 while let Some((v, expanded)) = stack.pop() {
181 if expanded {
182 result.push(v);
183 } else {
184 stack.push((v, true));
185 for &c in csr_children(v, offsets, children).iter().rev() {
186 stack.push((c as usize, false));
187 }
188 }
189 }
190 result
191 }
192
193 #[allow(clippy::too_many_arguments)]
194 fn add_microset(
195 ms_root: u32,
196 split_children: &[u32],
197 offsets: &[u32],
198 children: &[u32],
199 assigned: &mut [bool],
200 node_info: &mut [NodeInfo],
201 microsets: &mut Vec<Microset>,
202 all_nodes: &mut Vec<u32>,
203 ) {
204 let ms_id = microsets.len() as u32;
205 let nodes_offset = all_nodes.len() as u32;
206 let mut child_counts = [0u32; 16];
207 let mut count = 0usize;
208
209 let mut stack: Vec<u32> = Vec::new();
210 for &c in split_children.iter().rev() {
211 if !assigned[c as usize] {
212 stack.push(c);
213 }
214 }
215
216 while let Some(v) = stack.pop() {
217 debug_assert!(!assigned[v as usize]);
218 let idx = count;
219 all_nodes.push(v);
220 assigned[v as usize] = true;
221 node_info[v as usize].micro = ms_id;
222 node_info[v as usize].number = idx as u16;
223
224 let mut cc = 0u32;
225 for &child in csr_children(v as usize, offsets, children).iter().rev() {
226 if !assigned[child as usize] {
227 stack.push(child);
228 cc += 1;
229 }
230 }
231 child_counts[idx] = cc;
232 count += 1;
233 }
234
235 let forest = encode_forest(&child_counts, count);
236 microsets.push(Microset {
237 nodes_offset,
238 mark: 0,
239 forest,
240 root: ms_root,
241 });
242 }
243
244 fn add_final_microset(
245 root: usize,
246 offsets: &[u32],
247 children: &[u32],
248 assigned: &mut [bool],
249 node_info: &mut [NodeInfo],
250 microsets: &mut Vec<Microset>,
251 all_nodes: &mut Vec<u32>,
252 ) {
253 let ms_id = microsets.len() as u32;
254 let nodes_offset = all_nodes.len() as u32;
255 let mut child_counts = [0u32; 16];
256 let mut count = 0usize;
257
258 let mut stack = vec![root as u32];
259 while let Some(v) = stack.pop() {
260 debug_assert!(!assigned[v as usize]);
261 let idx = count;
262 all_nodes.push(v);
263 assigned[v as usize] = true;
264 node_info[v as usize].micro = ms_id;
265 node_info[v as usize].number = idx as u16;
266
267 let mut cc = 0u32;
268 for &child in csr_children(v as usize, offsets, children).iter().rev() {
269 if !assigned[child as usize] {
270 stack.push(child);
271 cc += 1;
272 }
273 }
274 if idx < 16 {
275 child_counts[idx] = cc;
276 }
277 count += 1;
278 }
279
280 let forest = encode_forest(&child_counts, count);
281 microsets.push(Microset {
282 nodes_offset,
283 mark: 0,
284 forest,
285 root: NO_PARENT,
286 });
287 }
288
289 #[inline]
292 pub fn link(&mut self, v: usize) {
293 assert!(
294 self.node_info[v].parent != NO_PARENT,
295 "cannot link the root (it has no parent)"
296 );
297 let info = &self.node_info[v];
298 self.microsets[info.micro as usize].mark |= 1 << info.number;
299 }
300
301 #[inline]
304 #[must_use]
305 pub fn find(&mut self, v: usize) -> usize {
306 let mut x = v as u32;
307 let mut y = microfind(
308 x,
309 &self.node_info,
310 &self.microsets,
311 &self.all_nodes,
312 &self.answer_table,
313 );
314
315 debug_assert_ne!(y, NO_PARENT, "root must always be a set name");
316
317 let x_micro = self.node_info[x as usize].micro;
318 let y_micro = self.node_info[y as usize].micro;
319
320 if x_micro != y_micro {
321 x = self.macroset.top(y);
322
323 loop {
324 y = microfind(
325 x,
326 &self.node_info,
327 &self.microsets,
328 &self.all_nodes,
329 &self.answer_table,
330 );
331 debug_assert_ne!(y, NO_PARENT, "root must always be a set name");
332
333 let x_micro = self.node_info[x as usize].micro;
334 let y_micro = self.node_info[y as usize].micro;
335
336 if x_micro == y_micro {
337 break;
338 }
339
340 self.macroset.unite(y, x);
342 x = self.macroset.top(y);
343 }
344 }
345
346 y as usize
347 }
348
349 #[must_use]
350 pub fn len(&self) -> usize {
351 self.n
352 }
353
354 #[must_use]
355 pub fn is_empty(&self) -> bool {
356 self.n == 0
357 }
358}