use super::avl_forest::AvlForestHy as AvlForest;
use std::fmt::Debug;
type IdType = usize;
type NodeId = (usize, usize);
fn edge_id(u: IdType, v: IdType) -> NodeId {
debug_assert!(u != v);
(u, v)
}
fn vert_id(v: IdType) -> NodeId {
(v, v)
}
#[derive(Debug, Default)]
pub struct EulerForest {
nodes: AvlForest,
}
impl EulerForest {
pub fn new() -> Self {
Default::default()
}
pub fn ensure_vertex(&mut self, v: IdType) {
self.nodes.ensure(vert_id(v));
}
pub fn add_edge(&mut self, v1: IdType, v2: IdType) {
debug_assert!(self.is_seen(v1));
debug_assert!(self.is_seen(v2));
debug_assert!(!self.same_root(v1, v2));
let e12 = edge_id(v1, v2);
let e21 = edge_id(v2, v1);
let v1 = vert_id(v1);
let v2 = vert_id(v2);
self.nodes.ensure(e12);
self.nodes.ensure(e21);
let u1 = self.nodes.prev(v1);
let w1 = self.nodes.next(v1);
let u2 = self.nodes.prev(v2);
let w2 = self.nodes.next(v2);
self.nodes.split(v1);
self.nodes.split(v2);
let r = self.nodes.get_root(v1);
for &node in
[Some(e12), Some(v2), w2, u2, Some(e21), w1, u1].iter().flatten()
{
self.nodes.concat(r, node);
}
}
pub fn remove_edge(&mut self, v1: IdType, v2: IdType) {
debug_assert!(self.is_seen(v1));
debug_assert!(self.is_seen(v2));
debug_assert!(self.same_root(v1, v2));
let e12 = edge_id(v1, v2);
let e21 = edge_id(v2, v1);
let u1 = self.nodes.prev(e12);
let u2 = self.nodes.next(e12);
let u3 = self.nodes.prev(e21);
let u4 = self.nodes.next(e21);
self.nodes.split(e12);
self.nodes.split(e21);
if let Some((u2, u3)) = u2.zip(u3) {
self.nodes.concat(u2, u3);
}
if let Some((u4, u1)) = u4.zip(u1) {
self.nodes.concat(u4, u1);
}
}
pub fn same_root(&self, v1: IdType, v2: IdType) -> bool {
self.nodes.same_root(vert_id(v1), vert_id(v2))
}
pub fn get_time(&self) -> usize {
self.nodes.get_time()
}
pub fn get_space(&self) -> usize {
self.nodes.get_space()
}
pub fn is_seen(&self, v: IdType) -> bool {
self.nodes.is_seen(vert_id(v))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add_vertex() {
let mut g = EulerForest::new();
assert!(!g.is_seen(1));
assert!(!g.is_seen(2));
assert!(!g.is_seen(3));
g.ensure_vertex(1);
g.ensure_vertex(2);
g.ensure_vertex(3);
assert!(g.is_seen(1));
assert!(g.is_seen(2));
assert!(g.is_seen(1));
assert!(!g.is_seen(0));
assert!(!g.is_seen(4));
assert!(g.same_root(2, 2));
assert!(!g.same_root(1, 2));
assert!(!g.same_root(2, 3));
assert!(!g.same_root(3, 1));
}
#[test]
#[should_panic]
fn test_query_nonexistent_1() {
let g = EulerForest::new();
g.same_root(1, 1);
}
#[test]
#[should_panic]
fn test_query_nonexistent_2() {
let g = EulerForest::new();
g.same_root(1, 2);
}
#[test]
#[should_panic]
fn test_edge_nonexistent_1() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.add_edge(1, 2);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_edge_nonexistent_2() {
let mut g = EulerForest::new();
g.ensure_vertex(2);
g.add_edge(1, 2);
}
#[test]
fn test_two_vertices() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.ensure_vertex(2);
g.add_edge(1, 2);
assert!(g.same_root(1, 2));
assert!(g.same_root(2, 1));
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_add_edge_twice() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.ensure_vertex(2);
g.add_edge(1, 2);
g.add_edge(1, 2);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_add_self_edge() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.add_edge(1, 1);
}
#[test]
fn test_add_edges() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.ensure_vertex(2);
g.ensure_vertex(3);
g.add_edge(1, 2);
assert!(g.same_root(1, 2));
assert!(!g.same_root(1, 3));
assert!(!g.same_root(2, 3));
g.add_edge(3, 2);
assert!(g.same_root(1, 2));
assert!(g.same_root(2, 3));
}
#[test]
fn test_add_edges_complicated() {
let mut g = EulerForest::new();
for i in 0..10 {
g.ensure_vertex(i);
}
g.add_edge(0, 1);
g.add_edge(2, 3);
g.add_edge(1, 3);
g.add_edge(6, 5);
g.add_edge(5, 4);
g.add_edge(4, 7);
g.add_edge(3, 8);
g.add_edge(9, 2);
assert!(g.same_root(0, 1));
assert!(g.same_root(1, 2));
assert!(g.same_root(2, 3));
assert!(g.same_root(3, 8));
assert!(g.same_root(8, 9));
assert!(g.same_root(4, 5));
assert!(g.same_root(5, 6));
assert!(g.same_root(6, 7));
assert!(!g.same_root(3, 4));
assert!(!g.same_root(7, 8));
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_add_cycle_2() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.ensure_vertex(2);
g.add_edge(1, 2);
g.add_edge(2, 1);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_add_cycle_3() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.ensure_vertex(2);
g.ensure_vertex(3);
g.add_edge(1, 2);
g.add_edge(2, 3);
g.add_edge(3, 1);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic]
fn test_add_cycle_4() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.ensure_vertex(2);
g.ensure_vertex(3);
g.ensure_vertex(4);
g.add_edge(1, 2);
g.add_edge(3, 4);
g.add_edge(2, 3);
g.add_edge(4, 1);
}
#[test]
fn test_add_two_parents() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.ensure_vertex(2);
g.ensure_vertex(3);
g.add_edge(3, 1);
assert!(g.same_root(1, 3));
assert!(!g.same_root(1, 2));
g.add_edge(3, 2);
assert!(g.same_root(1, 2));
assert!(g.same_root(2, 3));
}
#[test]
fn test_remove_edge_1() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.ensure_vertex(2);
g.ensure_vertex(3);
g.ensure_vertex(4);
g.add_edge(1, 2);
g.add_edge(2, 3);
g.add_edge(3, 4);
assert!(g.same_root(1, 2));
assert!(g.same_root(2, 3));
assert!(g.same_root(3, 4));
g.remove_edge(2, 3);
assert!(g.same_root(1, 2));
assert!(g.same_root(3, 4));
assert!(!g.same_root(2, 3));
}
#[test]
fn test_remove_edge_2() {
let mut g = EulerForest::new();
g.ensure_vertex(1);
g.ensure_vertex(2);
g.ensure_vertex(3);
g.ensure_vertex(4);
g.add_edge(3, 4);
g.add_edge(1, 2);
g.add_edge(2, 3);
assert!(g.same_root(1, 4));
g.remove_edge(1, 2);
assert!(!g.same_root(1, 2));
assert!(g.same_root(2, 3));
assert!(g.same_root(3, 4));
g.remove_edge(2, 3);
assert!(!g.same_root(1, 2));
assert!(!g.same_root(1, 3));
assert!(!g.same_root(2, 3));
assert!(g.same_root(3, 4));
}
}