#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct UnionFindV3 {
parent: Vec<usize>,
rank: Vec<u32>,
size: Vec<usize>,
num_components: usize,
}
impl UnionFindV3 {
pub fn new(n: usize) -> Self {
UnionFindV3 {
parent: (0..n).collect(),
rank: vec![0; n],
size: vec![1; n],
num_components: n,
}
}
pub fn find(&mut self, x: usize) -> usize {
if self.parent[x] != x {
self.parent[x] = self.find(self.parent[x]);
}
self.parent[x]
}
pub fn union(&mut self, a: usize, b: usize) -> bool {
let ra = self.find(a);
let rb = self.find(b);
if ra == rb {
return false;
}
if self.rank[ra] < self.rank[rb] {
self.parent[ra] = rb;
self.size[rb] += self.size[ra];
} else if self.rank[ra] > self.rank[rb] {
self.parent[rb] = ra;
self.size[ra] += self.size[rb];
} else {
self.parent[rb] = ra;
self.size[ra] += self.size[rb];
self.rank[ra] += 1;
}
self.num_components -= 1;
true
}
pub fn connected(&mut self, a: usize, b: usize) -> bool {
self.find(a) == self.find(b)
}
pub fn component_size(&mut self, x: usize) -> usize {
let root = self.find(x);
self.size[root]
}
pub fn num_components(&self) -> usize {
self.num_components
}
pub fn len(&self) -> usize {
self.parent.len()
}
pub fn is_empty(&self) -> bool {
self.parent.is_empty()
}
}
pub fn new_union_find_v3(n: usize) -> UnionFindV3 {
UnionFindV3::new(n)
}
pub fn uf3_union(uf: &mut UnionFindV3, a: usize, b: usize) -> bool {
uf.union(a, b)
}
pub fn uf3_find(uf: &mut UnionFindV3, x: usize) -> usize {
uf.find(x)
}
pub fn uf3_connected(uf: &mut UnionFindV3, a: usize, b: usize) -> bool {
uf.connected(a, b)
}
pub fn uf3_num_components(uf: &UnionFindV3) -> usize {
uf.num_components()
}
pub fn uf3_component_size(uf: &mut UnionFindV3, x: usize) -> usize {
uf.component_size(x)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_initial_components() {
let uf = new_union_find_v3(5);
assert_eq!(uf3_num_components(&uf), 5 );
}
#[test]
fn test_union_reduces_components() {
let mut uf = new_union_find_v3(4);
uf3_union(&mut uf, 0, 1);
assert_eq!(uf3_num_components(&uf), 3 );
}
#[test]
fn test_connected() {
let mut uf = new_union_find_v3(5);
uf3_union(&mut uf, 2, 3);
assert!(uf3_connected(&mut uf, 2, 3) );
assert!(!uf3_connected(&mut uf, 0, 3));
}
#[test]
fn test_transitive() {
let mut uf = new_union_find_v3(5);
uf3_union(&mut uf, 0, 1);
uf3_union(&mut uf, 1, 2);
assert!(uf3_connected(&mut uf, 0, 2) );
}
#[test]
fn test_union_same_set_returns_false() {
let mut uf = new_union_find_v3(3);
uf3_union(&mut uf, 0, 1);
assert!(!uf3_union(&mut uf, 0, 1) );
}
#[test]
fn test_component_size() {
let mut uf = new_union_find_v3(5);
uf3_union(&mut uf, 0, 1);
uf3_union(&mut uf, 1, 2);
assert_eq!(uf3_component_size(&mut uf, 0), 3 );
}
#[test]
fn test_find_consistency() {
let mut uf = new_union_find_v3(3);
uf3_union(&mut uf, 0, 1);
assert_eq!(uf3_find(&mut uf, 0), uf3_find(&mut uf, 1) );
}
#[test]
fn test_len() {
let uf = new_union_find_v3(10);
assert_eq!(uf.len(), 10 );
}
#[test]
fn test_all_merged() {
let mut uf = new_union_find_v3(4);
uf3_union(&mut uf, 0, 1);
uf3_union(&mut uf, 2, 3);
uf3_union(&mut uf, 0, 2);
assert_eq!(uf3_num_components(&uf), 1 );
}
#[test]
fn test_empty() {
let uf = new_union_find_v3(0);
assert!(uf.is_empty() );
}
}