pub mod cache_opt;
pub mod polylog;
use crate::euler::EulerTourTree;
use crate::graph::VertexId;
use std::collections::{HashMap, HashSet};
#[derive(Debug, Clone)]
pub struct DynamicConnectivity {
parent: HashMap<VertexId, VertexId>,
rank: HashMap<VertexId, usize>,
edges: HashSet<(VertexId, VertexId)>,
vertex_count: usize,
component_count: usize,
ett: EulerTourTree,
ett_synced: bool,
}
impl DynamicConnectivity {
pub fn new() -> Self {
Self {
parent: HashMap::new(),
rank: HashMap::new(),
edges: HashSet::new(),
vertex_count: 0,
component_count: 0,
ett: EulerTourTree::new(),
ett_synced: true,
}
}
pub fn add_vertex(&mut self, v: VertexId) {
if !self.parent.contains_key(&v) {
self.parent.insert(v, v);
self.rank.insert(v, 0);
self.vertex_count += 1;
self.component_count += 1;
let _ = self.ett.make_tree(v);
}
}
pub fn insert_edge(&mut self, u: VertexId, v: VertexId) {
self.add_vertex(u);
self.add_vertex(v);
let edge = if u < v { (u, v) } else { (v, u) };
if self.edges.insert(edge) {
let root_u = self.find(u);
let root_v = self.find(v);
if root_u != root_v {
self.union(root_u, root_v);
let _ = self.ett.link(u, v);
}
}
}
pub fn delete_edge(&mut self, u: VertexId, v: VertexId) {
let edge = if u < v { (u, v) } else { (v, u) };
if self.edges.remove(&edge) {
self.ett_synced = false;
self.rebuild();
}
}
pub fn is_connected(&self) -> bool {
self.component_count == 1
}
pub fn connected(&mut self, u: VertexId, v: VertexId) -> bool {
if !self.parent.contains_key(&u) || !self.parent.contains_key(&v) {
return false;
}
self.find(u) == self.find(v)
}
#[inline]
pub fn connected_fast(&self, u: VertexId, v: VertexId) -> Option<bool> {
if !self.ett_synced {
return None;
}
Some(self.ett.connected(u, v))
}
pub fn component_count(&self) -> usize {
self.component_count
}
pub fn vertex_count(&self) -> usize {
self.vertex_count
}
fn find(&mut self, v: VertexId) -> VertexId {
let parent = *self.parent.get(&v).expect("Vertex not found");
if parent != v {
let root = self.find(parent);
self.parent.insert(v, root);
root
} else {
v
}
}
fn union(&mut self, u: VertexId, v: VertexId) {
if u == v {
return;
}
let rank_u = *self.rank.get(&u).unwrap_or(&0);
let rank_v = *self.rank.get(&v).unwrap_or(&0);
if rank_u < rank_v {
self.parent.insert(u, v);
} else if rank_u > rank_v {
self.parent.insert(v, u);
} else {
self.parent.insert(v, u);
self.rank.insert(u, rank_u + 1);
}
self.component_count -= 1;
}
fn rebuild(&mut self) {
let vertices: Vec<VertexId> = self.parent.keys().copied().collect();
self.component_count = vertices.len();
for &v in &vertices {
self.parent.insert(v, v);
self.rank.insert(v, 0);
}
self.ett = EulerTourTree::new();
for &v in &vertices {
let _ = self.ett.make_tree(v);
}
let edges: Vec<(VertexId, VertexId)> = self.edges.iter().copied().collect();
for (u, v) in edges {
let root_u = self.find(u);
let root_v = self.find(v);
if root_u != root_v {
self.union(root_u, root_v);
let _ = self.ett.link(u, v);
}
}
self.ett_synced = true;
}
}
impl Default for DynamicConnectivity {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let dc = DynamicConnectivity::new();
assert_eq!(dc.vertex_count(), 0);
assert_eq!(dc.component_count(), 0);
}
#[test]
fn test_add_vertex() {
let mut dc = DynamicConnectivity::new();
dc.add_vertex(0);
assert_eq!(dc.vertex_count(), 1);
assert_eq!(dc.component_count(), 1);
dc.add_vertex(1);
assert_eq!(dc.vertex_count(), 2);
assert_eq!(dc.component_count(), 2);
dc.add_vertex(0);
assert_eq!(dc.vertex_count(), 2);
assert_eq!(dc.component_count(), 2);
}
#[test]
fn test_insert_edge_basic() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 1);
assert_eq!(dc.vertex_count(), 2);
assert_eq!(dc.component_count(), 1);
assert!(dc.connected(0, 1));
}
#[test]
fn test_insert_edge_chain() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 1);
dc.insert_edge(1, 2);
dc.insert_edge(2, 3);
assert_eq!(dc.vertex_count(), 4);
assert_eq!(dc.component_count(), 1);
assert!(dc.connected(0, 3));
}
#[test]
fn test_is_connected() {
let mut dc = DynamicConnectivity::new();
dc.add_vertex(0);
dc.add_vertex(1);
assert!(!dc.is_connected());
dc.insert_edge(0, 1);
assert!(dc.is_connected());
dc.add_vertex(2);
assert!(!dc.is_connected());
dc.insert_edge(1, 2);
assert!(dc.is_connected());
}
#[test]
fn test_delete_edge() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 1);
dc.insert_edge(1, 2);
assert!(dc.connected(0, 2));
dc.delete_edge(1, 2);
assert!(dc.connected(0, 1));
assert!(!dc.connected(0, 2));
assert_eq!(dc.component_count(), 2);
}
#[test]
fn test_delete_edge_normalized() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 1);
assert!(dc.connected(0, 1));
dc.delete_edge(1, 0);
assert!(!dc.connected(0, 1));
}
#[test]
fn test_multiple_components() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 1);
dc.insert_edge(1, 2);
dc.insert_edge(3, 4);
dc.add_vertex(5);
assert_eq!(dc.vertex_count(), 6);
assert_eq!(dc.component_count(), 3);
assert!(dc.connected(0, 2));
assert!(dc.connected(3, 4));
assert!(!dc.connected(0, 3));
assert!(!dc.connected(0, 5));
}
#[test]
fn test_path_compression() {
let mut dc = DynamicConnectivity::new();
for i in 0..10 {
dc.insert_edge(i, i + 1);
}
assert!(dc.connected(0, 10));
let root = dc.find(0);
for i in 0..=10 {
assert_eq!(dc.find(i), root);
}
}
#[test]
fn test_union_by_rank() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 1);
dc.insert_edge(0, 2);
dc.insert_edge(0, 3);
dc.insert_edge(4, 5);
dc.insert_edge(0, 4);
assert_eq!(dc.component_count(), 1);
assert!(dc.connected(1, 5));
}
#[test]
fn test_rebuild_after_multiple_deletions() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 1);
dc.insert_edge(0, 2);
dc.insert_edge(0, 3);
dc.insert_edge(1, 2);
dc.insert_edge(1, 3);
dc.insert_edge(2, 3);
assert!(dc.is_connected());
dc.delete_edge(0, 1);
dc.delete_edge(0, 2);
dc.delete_edge(0, 3);
assert!(!dc.is_connected());
assert_eq!(dc.component_count(), 2);
assert!(!dc.connected(0, 1));
assert!(dc.connected(1, 2));
assert!(dc.connected(1, 3));
}
#[test]
fn test_connected_nonexistent_vertex() {
let mut dc = DynamicConnectivity::new();
dc.add_vertex(0);
assert!(!dc.connected(0, 999));
assert!(!dc.connected(999, 0));
}
#[test]
fn test_self_loop() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 0);
assert_eq!(dc.vertex_count(), 1);
assert_eq!(dc.component_count(), 1);
assert!(dc.connected(0, 0));
}
#[test]
fn test_duplicate_edges() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 1);
dc.insert_edge(0, 1); dc.insert_edge(1, 0);
assert_eq!(dc.vertex_count(), 2);
assert_eq!(dc.component_count(), 1);
}
}