#[derive(Debug, Clone)]
pub struct DisjointSets(Vec<usize>);
impl DisjointSets {
pub fn new(n: usize) -> Self {
DisjointSets((0..n).collect())
}
pub fn find(&mut self, mut i: usize) -> usize {
while self.0[i] != i {
self.0[i] = self.0[self.0[i]];
i = self.0[i];
}
i
}
pub fn union(&mut self, a: usize, b: usize) -> bool {
let (a, b) = (self.find(a), self.find(b));
if a == b {
return false;
}
self.0[a.max(b)] = a.min(b);
true
}
}
#[cfg(test)]
mod tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn matches_a_naive_partition(
n in 1usize..40,
pairs in prop::collection::vec((0usize..40, 0usize..40), 0..60),
) {
let mut sets = DisjointSets::new(n);
let mut label: Vec<usize> = (0..n).collect();
for (a, b) in pairs {
let (a, b) = (a % n, b % n);
let merged = sets.union(a, b);
let (la, lb) = (label[a], label[b]);
prop_assert_eq!(merged, la != lb);
let (keep, drop) = (la.min(lb), la.max(lb));
for l in &mut label {
if *l == drop {
*l = keep;
}
}
}
for (i, &l) in label.iter().enumerate() {
prop_assert_eq!(sets.find(i), l);
}
}
}
}