use std::cmp::{max, min};
use std::vec::Vec;
pub struct UnionFind {
is_finalized: bool,
components: i32,
representatives: Vec<i32>,
}
impl UnionFind {
pub fn new(size: i32) -> UnionFind {
assert!(size > 0);
UnionFind {
is_finalized: false,
components: size,
representatives: vec![-1; size as usize],
}
}
pub fn representative(&mut self, mut element: i32) -> i32 {
assert!(element >= 0);
let first = element;
let mut next = self.representatives[element as usize];
while next >= 0 {
assert!(next > element);
element = next;
next = self.representatives[element as usize];
}
if element != first {
self.representatives[first as usize] = element;
}
element
}
pub fn merge(&mut self, left: i32, right: i32) {
assert!(!self.is_finalized);
let left_representative = self.representative(left);
let right_representative = self.representative(right);
assert!(left_representative != right_representative);
let low = min(left_representative, right_representative);
let high = max(left_representative, right_representative);
self.representatives[low as usize] = high;
self.components -= 1;
if left != high {
self.representatives[left as usize] = high;
}
if right != high {
self.representatives[right as usize] = high;
}
}
pub fn components(&self) -> i32 {
self.components
}
pub fn finalize(&mut self) {
assert!(!self.is_finalized);
let mut component: i32 = 0;
for representative in self.representatives.iter_mut() {
if *representative < 0 {
*representative = -1 - component as i32;
component += 1;
}
}
self.is_finalized = true;
}
pub fn component(&mut self, element: i32) -> i32 {
let representative = self.representative(element);
-1 - self.representatives[representative as usize]
}
}