use std::collections::HashMap;
pub struct UnionFind {
parent: Vec<usize>,
}
impl UnionFind {
#[must_use]
pub fn new(size: usize) -> Self {
Self {
parent: (0..size).collect(),
}
}
#[must_use]
pub const fn len(&self) -> usize {
self.parent.len()
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.parent.is_empty()
}
pub fn find(&mut self, i: usize) -> usize {
if self.parent[i] != i {
let root = self.find(self.parent[i]);
self.parent[i] = root;
}
self.parent[i]
}
pub fn union(&mut self, i: usize, j: usize) {
let root_i = self.find(i);
let root_j = self.find(j);
if root_i != root_j {
self.parent[root_i] = root_j;
}
}
pub fn groups(&mut self) -> Vec<Vec<usize>> {
let mut position_of_root: HashMap<usize, usize> = HashMap::new();
let mut groups: Vec<Vec<usize>> = Vec::new();
for i in 0..self.len() {
let root = self.find(i);
if let Some(&position) = position_of_root.get(&root) {
groups[position].push(i);
} else {
position_of_root.insert(root, groups.len());
groups.push(vec![i]);
}
}
groups
}
}