1use crate::{MinCutError, Result};
54use std::collections::HashMap;
55
56pub type NodeId = u64;
58
59#[derive(Debug, Clone)]
65struct XorShift64 {
66 state: u64,
67}
68
69impl XorShift64 {
70 #[inline]
71 fn new(seed: u64) -> Self {
72 Self {
73 state: if seed == 0 { 0x123456789abcdef0 } else { seed },
74 }
75 }
76
77 #[inline(always)]
82 fn next(&mut self) -> u64 {
83 self.state ^= self.state >> 12;
84 self.state ^= self.state << 25;
85 self.state ^= self.state >> 27;
86 self.state.wrapping_mul(0x2545f4914f6cdd1d)
87 }
88}
89
90#[derive(Debug, Clone)]
92struct TreapNode {
93 vertex: NodeId,
95 priority: u64,
97 left: Option<usize>,
99 right: Option<usize>,
101 parent: Option<usize>,
103 size: usize,
105 value: f64,
107 subtree_aggregate: f64,
109 lazy_value: Option<f64>,
111}
112
113impl TreapNode {
114 #[inline]
116 fn new(vertex: NodeId, priority: u64, value: f64) -> Self {
117 Self {
118 vertex,
119 priority,
120 left: None,
121 right: None,
122 parent: None,
123 size: 1,
124 value,
125 subtree_aggregate: value,
126 lazy_value: None,
127 }
128 }
129}
130
131#[derive(Debug, Clone)]
133pub struct EulerTourTree {
134 nodes: Vec<TreapNode>,
136 free_list: Vec<usize>,
138 first_occurrence: HashMap<NodeId, usize>,
140 last_occurrence: HashMap<NodeId, usize>,
142 edge_to_node: HashMap<(NodeId, NodeId), usize>,
144 enter_to_exit: HashMap<usize, usize>,
147 roots: HashMap<NodeId, usize>,
149 rng: XorShift64,
151}
152
153impl EulerTourTree {
154 #[inline]
156 pub fn new() -> Self {
157 Self::with_seed(42)
158 }
159
160 #[inline]
165 pub fn with_seed(seed: u64) -> Self {
166 Self::with_seed_and_capacity(seed, 16)
167 }
168
169 pub fn with_seed_and_capacity(seed: u64, capacity: usize) -> Self {
174 Self {
175 nodes: Vec::with_capacity(capacity),
176 free_list: Vec::with_capacity(capacity / 4),
177 first_occurrence: HashMap::with_capacity(capacity),
178 last_occurrence: HashMap::with_capacity(capacity),
179 edge_to_node: HashMap::with_capacity(capacity),
180 enter_to_exit: HashMap::with_capacity(capacity),
181 roots: HashMap::with_capacity(capacity),
182 rng: XorShift64::new(seed),
183 }
184 }
185
186 #[inline]
188 pub fn make_tree(&mut self, v: NodeId) -> Result<()> {
189 if self.first_occurrence.contains_key(&v) {
190 return Err(self.vertex_exists_error(v));
191 }
192
193 let priority = self.rng.next();
194 let idx = self.allocate_node(v, priority, 0.0);
195
196 self.first_occurrence.insert(v, idx);
197 self.last_occurrence.insert(v, idx);
198 self.roots.insert(v, idx);
199
200 Ok(())
201 }
202
203 #[cold]
204 #[inline(never)]
205 fn vertex_exists_error(&self, v: NodeId) -> MinCutError {
206 MinCutError::InternalError(format!("Vertex {} already exists in a tree", v))
207 }
208
209 pub fn link(&mut self, u: NodeId, v: NodeId) -> Result<()> {
211 let u_idx = *self
213 .first_occurrence
214 .get(&u)
215 .ok_or_else(|| MinCutError::InvalidVertex(u))?;
216 let v_root = *self
217 .first_occurrence
218 .get(&v)
219 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
220
221 if self.connected(u, v) {
223 return Err(MinCutError::EdgeExists(u, v));
224 }
225
226 self.reroot_internal(u)?;
228
229 let u_root = self.find_root_idx(u_idx)?;
231
232 let priority1 = self.rng.next();
234 let priority2 = self.rng.next();
235 let enter_v = self.allocate_node(v, priority1, 0.0);
236 let exit_v = self.allocate_node(u, priority2, 0.0);
237
238 self.edge_to_node.insert((u, v), enter_v);
240 self.enter_to_exit.insert(enter_v, exit_v);
241
242 let merged1 = self.merge(Some(u_root), Some(enter_v));
244 let merged2 = self.merge(merged1, Some(v_root));
245 let final_root = self.merge(merged2, Some(exit_v));
246
247 if let Some(root) = final_root {
249 let root_vertex = self.nodes[root].vertex;
250 self.update_root_mapping(root, root_vertex);
251 }
252
253 Ok(())
254 }
255
256 pub fn cut(&mut self, u: NodeId, v: NodeId) -> Result<()> {
261 let edge_node = self
263 .edge_to_node
264 .remove(&(u, v))
265 .or_else(|| self.edge_to_node.remove(&(v, u)))
266 .ok_or_else(|| MinCutError::EdgeNotFound(u, v))?;
267
268 self.reroot_internal(u)?;
270
271 let enter_v = edge_node;
273
274 let exit_u_idx = self.find_matching_exit(enter_v)?;
276
277 self.enter_to_exit.remove(&enter_v);
279
280 let pos1 = self.get_position(enter_v);
282 let pos2 = self.get_position(exit_u_idx);
283
284 let (start_pos, end_pos) = if pos1 < pos2 {
286 (pos1, pos2)
287 } else {
288 (pos2, pos1)
289 };
290
291 let root = self.find_root_idx(*self.first_occurrence.get(&u).unwrap())?;
293
294 let (left, rest) = self.split(root, start_pos);
297 if rest.is_none() {
298 return Err(MinCutError::InternalError("Split failed".to_string()));
299 }
300
301 let (enter_and_middle, right) = self.split(rest.unwrap(), end_pos - start_pos + 1);
302
303 let (enter_node, middle_and_exit) = self.split_first(enter_and_middle);
305
306 let (middle, exit_node) = self.split_last(middle_and_exit);
308
309 if let Some(idx) = enter_node {
311 self.free_node(idx);
312 }
313 if let Some(idx) = exit_node {
314 self.free_node(idx);
315 }
316
317 let u_tree = self.merge(left, right);
319
320 let v_tree = middle;
322
323 if let Some(root_idx) = u_tree {
325 let root_vertex = self.nodes[root_idx].vertex;
326 self.update_root_mapping(root_idx, root_vertex);
327 }
328 if let Some(root_idx) = v_tree {
329 let root_vertex = self.nodes[root_idx].vertex;
330 self.update_root_mapping(root_idx, root_vertex);
331 }
332
333 Ok(())
334 }
335
336 #[inline]
338 pub fn connected(&self, u: NodeId, v: NodeId) -> bool {
339 match (self.first_occurrence.get(&u), self.first_occurrence.get(&v)) {
340 (Some(&u_idx), Some(&v_idx)) => {
341 let u_root = self.find_root_idx(u_idx);
342 let v_root = self.find_root_idx(v_idx);
343 matches!((u_root, v_root), (Ok(ur), Ok(vr)) if ur == vr)
344 }
345 _ => false,
346 }
347 }
348
349 #[inline]
351 pub fn find_root(&self, v: NodeId) -> Result<NodeId> {
352 let v_idx = *self
353 .first_occurrence
354 .get(&v)
355 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
356 let root_idx = self.find_root_idx(v_idx)?;
357 Ok(self.nodes[root_idx].vertex)
358 }
359
360 #[inline]
362 pub fn tree_size(&self, v: NodeId) -> Result<usize> {
363 let v_idx = *self
364 .first_occurrence
365 .get(&v)
366 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
367 let root_idx = self.find_root_idx(v_idx)?;
368
369 let vertices = self.collect_vertices(root_idx);
371 Ok(vertices.len())
372 }
373
374 #[inline]
376 pub fn subtree_size(&self, v: NodeId) -> Result<usize> {
377 let first_idx = *self
378 .first_occurrence
379 .get(&v)
380 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
381 let last_idx = *self
382 .last_occurrence
383 .get(&v)
384 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
385
386 if first_idx == last_idx {
387 return Ok(1); }
389
390 let pos1 = self.get_position(first_idx);
392 let pos2 = self.get_position(last_idx);
393 let range_size = pos2.saturating_sub(pos1) + 1;
394
395 Ok((range_size + 1) / 2)
396 }
397
398 #[inline]
400 pub fn subtree_aggregate(&self, v: NodeId) -> Result<f64> {
401 let first_idx = *self
402 .first_occurrence
403 .get(&v)
404 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
405
406 Ok(self.nodes[first_idx].subtree_aggregate)
408 }
409
410 #[inline]
412 pub fn update_value(&mut self, v: NodeId, value: f64) -> Result<()> {
413 let first_idx = *self
414 .first_occurrence
415 .get(&v)
416 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
417
418 self.nodes[first_idx].value = value;
419 self.pull_up(first_idx);
420
421 Ok(())
422 }
423
424 pub fn reroot(&mut self, v: NodeId) -> Result<()> {
426 self.reroot_internal(v)
427 }
428
429 #[inline]
431 pub fn len(&self) -> usize {
432 self.first_occurrence.len()
433 }
434
435 #[inline]
437 pub fn is_empty(&self) -> bool {
438 self.first_occurrence.is_empty()
439 }
440
441 pub fn bulk_make_trees(&mut self, vertices: &[NodeId]) -> Result<()> {
450 let count = vertices.len();
452 self.nodes.reserve(count);
453 self.first_occurrence.reserve(count);
454 self.last_occurrence.reserve(count);
455 self.roots.reserve(count);
456
457 for &v in vertices {
458 if self.first_occurrence.contains_key(&v) {
459 return Err(self.vertex_exists_error(v));
460 }
461
462 let priority = self.rng.next();
463 let idx = self.allocate_node(v, priority, 0.0);
464
465 self.first_occurrence.insert(v, idx);
466 self.last_occurrence.insert(v, idx);
467 self.roots.insert(v, idx);
468 }
469
470 Ok(())
471 }
472
473 pub fn bulk_update_values(&mut self, updates: &[(NodeId, f64)]) -> Result<()> {
480 let mut affected_indices = Vec::with_capacity(updates.len());
482
483 for &(v, value) in updates {
484 let idx = *self
485 .first_occurrence
486 .get(&v)
487 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
488
489 self.nodes[idx].lazy_value = Some(value);
490 affected_indices.push(idx);
491 }
492
493 for &idx in &affected_indices {
495 self.push_down_lazy(idx);
496 self.pull_up(idx);
497 }
498
499 Ok(())
500 }
501
502 pub fn bulk_link(&mut self, edges: &[(NodeId, NodeId)]) -> Result<()> {
508 for &(u, v) in edges {
510 self.first_occurrence
511 .get(&u)
512 .ok_or_else(|| MinCutError::InvalidVertex(u))?;
513 self.first_occurrence
514 .get(&v)
515 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
516 }
517
518 for &(u, v) in edges {
520 self.link(u, v)?;
521 }
522
523 Ok(())
524 }
525
526 #[inline]
533 fn find_root_idx(&self, mut idx: usize) -> Result<usize> {
534 let mut visited = 0;
535 let max_depth = self.nodes.len() * 2; while let Some(parent) = self.nodes[idx].parent {
538 idx = parent;
539 visited += 1;
540 if visited > max_depth {
541 return Err(MinCutError::InternalError(
542 "Cycle detected in tree".to_string(),
543 ));
544 }
545 }
546 Ok(idx)
547 }
548
549 fn reroot_internal(&mut self, v: NodeId) -> Result<()> {
551 let v_first = *self
552 .first_occurrence
553 .get(&v)
554 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
555
556 let root = self.find_root_idx(v_first)?;
558
559 let pos = self.get_position(v_first);
561 if pos == 0 {
562 return Ok(());
563 }
564
565 let (left, right) = self.split(root, pos);
568
569 let new_root = self.merge(right, left);
571
572 if let Some(root_idx) = new_root {
574 let root_vertex = self.nodes[root_idx].vertex;
575 self.update_root_mapping(root_idx, root_vertex);
576 }
577
578 Ok(())
579 }
580
581 fn update_root_mapping(&mut self, root_idx: usize, _root_vertex: NodeId) {
583 let vertices = self.collect_vertices(root_idx);
585 for vertex in vertices {
586 self.roots.insert(vertex, root_idx);
587 }
588 }
589
590 fn collect_vertices(&self, idx: usize) -> Vec<NodeId> {
595 let estimated_size = self.nodes[idx].size / 2;
596 let mut vertices = Vec::with_capacity(estimated_size);
597 let mut visited = std::collections::HashSet::with_capacity(estimated_size);
598 self.collect_vertices_helper(idx, &mut vertices, &mut visited);
599 vertices
600 }
601
602 #[inline]
603 fn collect_vertices_helper(
604 &self,
605 idx: usize,
606 vertices: &mut Vec<NodeId>,
607 visited: &mut std::collections::HashSet<NodeId>,
608 ) {
609 let node = &self.nodes[idx];
610 if visited.insert(node.vertex) {
611 vertices.push(node.vertex);
612 }
613
614 if let Some(left) = node.left {
615 self.collect_vertices_helper(left, vertices, visited);
616 }
617 if let Some(right) = node.right {
618 self.collect_vertices_helper(right, vertices, visited);
619 }
620 }
621
622 #[inline]
627 fn find_matching_exit(&self, enter_idx: usize) -> Result<usize> {
628 self.enter_to_exit.get(&enter_idx).copied().ok_or_else(|| {
629 MinCutError::InternalError(format!(
630 "No matching exit node found for enter index {}",
631 enter_idx
632 ))
633 })
634 }
635
636 #[inline]
644 fn split(&mut self, root: usize, pos: usize) -> (Option<usize>, Option<usize>) {
645 if pos == 0 {
646 return (None, Some(root));
647 }
648
649 self.push_down_lazy(root);
651
652 let left_size = self.nodes[root]
653 .left
654 .map(|l| self.nodes[l].size)
655 .unwrap_or(0);
656
657 if pos <= left_size {
658 if let Some(left_child) = self.nodes[root].left {
660 let (split_left, split_right) = self.split(left_child, pos);
661 self.nodes[root].left = split_right;
662 if let Some(idx) = split_right {
663 self.nodes[idx].parent = Some(root);
664 }
665 self.pull_up(root);
666
667 if let Some(idx) = split_left {
668 self.nodes[idx].parent = None;
669 }
670
671 (split_left, Some(root))
672 } else {
673 (None, Some(root))
674 }
675 } else {
676 let right_pos = pos - left_size - 1;
678 if let Some(right_child) = self.nodes[root].right {
679 let (split_left, split_right) = self.split(right_child, right_pos);
680 self.nodes[root].right = split_left;
681 if let Some(idx) = split_left {
682 self.nodes[idx].parent = Some(root);
683 }
684 self.pull_up(root);
685
686 if let Some(idx) = split_right {
687 self.nodes[idx].parent = None;
688 }
689
690 (Some(root), split_right)
691 } else {
692 (Some(root), None)
693 }
694 }
695 }
696
697 #[inline]
704 fn merge(&mut self, left: Option<usize>, right: Option<usize>) -> Option<usize> {
705 match (left, right) {
706 (None, right) => right,
707 (left, None) => left,
708 (Some(l), Some(r)) => {
709 self.push_down_lazy(l);
711 self.push_down_lazy(r);
712
713 if self.nodes[l].priority > self.nodes[r].priority {
715 let new_right = self.merge(self.nodes[l].right, Some(r));
717 self.nodes[l].right = new_right;
718 if let Some(idx) = new_right {
719 self.nodes[idx].parent = Some(l);
720 }
721 self.nodes[l].parent = None;
722 self.pull_up(l);
723 Some(l)
724 } else {
725 let new_left = self.merge(Some(l), self.nodes[r].left);
727 self.nodes[r].left = new_left;
728 if let Some(idx) = new_left {
729 self.nodes[idx].parent = Some(r);
730 }
731 self.nodes[r].parent = None;
732 self.pull_up(r);
733 Some(r)
734 }
735 }
736 }
737 }
738
739 #[inline]
741 fn split_first(&mut self, root: Option<usize>) -> (Option<usize>, Option<usize>) {
742 match root {
743 None => (None, None),
744 Some(idx) => {
745 let (first, rest) = self.split(idx, 1);
746 (first, rest)
747 }
748 }
749 }
750
751 #[inline]
753 fn split_last(&mut self, root: Option<usize>) -> (Option<usize>, Option<usize>) {
754 match root {
755 None => (None, None),
756 Some(idx) => {
757 let size = self.nodes[idx].size;
758 if size == 0 {
759 return (None, None);
760 }
761 let (rest, last) = self.split(idx, size - 1);
762 (rest, last)
763 }
764 }
765 }
766
767 #[inline]
772 fn allocate_node(&mut self, vertex: NodeId, priority: u64, value: f64) -> usize {
773 if let Some(idx) = self.free_list.pop() {
774 self.nodes[idx] = TreapNode::new(vertex, priority, value);
775 idx
776 } else {
777 let idx = self.nodes.len();
778 self.nodes.push(TreapNode::new(vertex, priority, value));
779 idx
780 }
781 }
782
783 #[inline]
785 fn free_node(&mut self, idx: usize) {
786 self.nodes[idx].left = None;
788 self.nodes[idx].right = None;
789 self.nodes[idx].parent = None;
790 self.nodes[idx].lazy_value = None;
791 self.free_list.push(idx);
792 }
793
794 #[inline(always)]
800 fn push_down_lazy(&mut self, idx: usize) {
801 if let Some(lazy_val) = self.nodes[idx].lazy_value.take() {
802 self.nodes[idx].value = lazy_val;
804
805 if let Some(left) = self.nodes[idx].left {
807 self.nodes[left].lazy_value = Some(lazy_val);
808 }
809 if let Some(right) = self.nodes[idx].right {
810 self.nodes[right].lazy_value = Some(lazy_val);
811 }
812
813 self.pull_up(idx);
815 }
816 }
817
818 #[inline(always)]
823 fn pull_up(&mut self, idx: usize) {
824 let mut size = 1;
825 let mut aggregate = self.nodes[idx].value;
826
827 if let Some(left) = self.nodes[idx].left {
828 size += self.nodes[left].size;
829 aggregate += self.nodes[left].subtree_aggregate;
830 }
831
832 if let Some(right) = self.nodes[idx].right {
833 size += self.nodes[right].size;
834 aggregate += self.nodes[right].subtree_aggregate;
835 }
836
837 self.nodes[idx].size = size;
838 self.nodes[idx].subtree_aggregate = aggregate;
839 }
840
841 #[inline]
846 fn get_position(&self, idx: usize) -> usize {
847 let mut pos = self.nodes[idx]
848 .left
849 .map(|l| self.nodes[l].size)
850 .unwrap_or(0);
851 let mut current = idx;
852
853 while let Some(parent) = self.nodes[current].parent {
854 if self.nodes[parent].right == Some(current) {
855 pos += 1;
857 if let Some(left) = self.nodes[parent].left {
858 pos += self.nodes[left].size;
859 }
860 }
861 current = parent;
862 }
863
864 pos
865 }
866}
867
868impl Default for EulerTourTree {
869 fn default() -> Self {
870 Self::new()
871 }
872}
873
874#[cfg(test)]
875mod tests {
876 use super::*;
877
878 #[test]
879 fn test_make_tree() {
880 let mut ett = EulerTourTree::new();
881 assert!(ett.make_tree(1).is_ok());
882 assert!(ett.make_tree(2).is_ok());
883 assert_eq!(ett.len(), 2);
884 }
885
886 #[test]
887 fn test_singleton_tree() {
888 let mut ett = EulerTourTree::new();
889 ett.make_tree(1).unwrap();
890
891 assert_eq!(ett.tree_size(1).unwrap(), 1);
892 assert_eq!(ett.subtree_size(1).unwrap(), 1);
893 assert!(ett.connected(1, 1));
894 }
895
896 #[test]
897 fn test_link_two_vertices() {
898 let mut ett = EulerTourTree::new();
899 ett.make_tree(1).unwrap();
900 ett.make_tree(2).unwrap();
901
902 assert!(!ett.connected(1, 2));
903
904 ett.link(1, 2).unwrap();
905
906 assert!(ett.connected(1, 2));
907 assert_eq!(ett.tree_size(1).unwrap(), 2);
908 assert_eq!(ett.tree_size(2).unwrap(), 2);
909 }
910
911 #[test]
912 fn test_link_multiple_vertices() {
913 let mut ett = EulerTourTree::new();
914
915 for i in 1..=5 {
916 ett.make_tree(i).unwrap();
917 }
918
919 ett.link(1, 2).unwrap();
921 ett.link(2, 3).unwrap();
922 ett.link(3, 4).unwrap();
923 ett.link(4, 5).unwrap();
924
925 for i in 1..=5 {
927 for j in 1..=5 {
928 assert!(ett.connected(i, j));
929 }
930 }
931
932 assert_eq!(ett.tree_size(1).unwrap(), 5);
933 }
934
935 #[test]
936 fn test_update_value() {
937 let mut ett = EulerTourTree::new();
938 ett.make_tree(1).unwrap();
939
940 ett.update_value(1, 10.0).unwrap();
941 assert_eq!(ett.subtree_aggregate(1).unwrap(), 10.0);
942
943 ett.update_value(1, 25.5).unwrap();
944 assert_eq!(ett.subtree_aggregate(1).unwrap(), 25.5);
945 }
946
947 #[test]
948 fn test_reroot() {
949 let mut ett = EulerTourTree::new();
950 ett.make_tree(1).unwrap();
951 ett.make_tree(2).unwrap();
952 ett.make_tree(3).unwrap();
953
954 ett.link(1, 2).unwrap();
955 ett.link(1, 3).unwrap();
956
957 assert!(ett.connected(1, 2));
959 assert!(ett.connected(2, 3));
960 assert_eq!(ett.tree_size(1).unwrap(), 3);
961
962 ett.reroot(2).unwrap();
964
965 assert!(ett.connected(1, 2));
967 assert!(ett.connected(2, 3));
968 assert_eq!(ett.tree_size(2).unwrap(), 3);
969 }
970
971 #[test]
972 fn test_invalid_vertex() {
973 let ett = EulerTourTree::new();
974
975 assert!(matches!(
976 ett.find_root(999),
977 Err(MinCutError::InvalidVertex(999))
978 ));
979
980 assert!(!ett.connected(1, 2));
981 }
982
983 #[test]
984 fn test_edge_already_exists() {
985 let mut ett = EulerTourTree::new();
986 ett.make_tree(1).unwrap();
987 ett.make_tree(2).unwrap();
988
989 ett.link(1, 2).unwrap();
990
991 assert!(matches!(ett.link(1, 2), Err(MinCutError::EdgeExists(1, 2))));
993 }
994
995 #[test]
996 fn test_split_and_merge() {
997 let mut ett = EulerTourTree::new();
998 ett.make_tree(1).unwrap();
999 ett.make_tree(2).unwrap();
1000 ett.make_tree(3).unwrap();
1001
1002 ett.link(1, 2).unwrap();
1003 ett.link(2, 3).unwrap();
1004
1005 assert!(ett.connected(1, 3));
1007 assert_eq!(ett.tree_size(1).unwrap(), 3);
1008 }
1009
1010 #[test]
1011 fn test_tree_size_updates() {
1012 let mut ett = EulerTourTree::new();
1013
1014 for i in 1..=10 {
1015 ett.make_tree(i).unwrap();
1016 }
1017
1018 for i in 2..=10 {
1020 ett.link(1, i).unwrap();
1021 }
1022
1023 assert_eq!(ett.tree_size(1).unwrap(), 10);
1024 assert_eq!(ett.tree_size(5).unwrap(), 10);
1025 }
1026
1027 #[test]
1028 fn test_empty_tree() {
1029 let ett = EulerTourTree::new();
1030 assert!(ett.is_empty());
1031 assert_eq!(ett.len(), 0);
1032 }
1033
1034 #[test]
1035 fn test_subtree_aggregate_simple() {
1036 let mut ett = EulerTourTree::new();
1037 ett.make_tree(1).unwrap();
1038 ett.make_tree(2).unwrap();
1039
1040 ett.update_value(1, 5.0).unwrap();
1041 ett.update_value(2, 3.0).unwrap();
1042
1043 assert_eq!(ett.subtree_aggregate(1).unwrap(), 5.0);
1044 assert_eq!(ett.subtree_aggregate(2).unwrap(), 3.0);
1045 }
1046
1047 #[test]
1048 fn test_reproducible_with_seed() {
1049 let mut ett1 = EulerTourTree::with_seed(12345);
1050 let mut ett2 = EulerTourTree::with_seed(12345);
1051
1052 for i in 1..=5 {
1053 ett1.make_tree(i).unwrap();
1054 ett2.make_tree(i).unwrap();
1055 }
1056
1057 ett1.link(1, 2).unwrap();
1058 ett2.link(1, 2).unwrap();
1059
1060 assert_eq!(ett1.tree_size(1).unwrap(), ett2.tree_size(1).unwrap());
1061 }
1062
1063 #[test]
1064 fn test_large_tree() {
1065 let mut ett = EulerTourTree::new();
1066 let n = 100;
1067
1068 for i in 0..n {
1069 ett.make_tree(i).unwrap();
1070 }
1071
1072 for i in 0..n - 1 {
1074 ett.link(i, i + 1).unwrap();
1075 }
1076
1077 assert_eq!(ett.tree_size(0).unwrap(), n as usize);
1078 assert_eq!(ett.tree_size(n - 1).unwrap(), n as usize);
1079 assert!(ett.connected(0, n - 1));
1080 }
1081
1082 #[test]
1083 fn test_multiple_trees() {
1084 let mut ett = EulerTourTree::new();
1085
1086 ett.make_tree(1).unwrap();
1088 ett.make_tree(2).unwrap();
1089 ett.make_tree(3).unwrap();
1090 ett.make_tree(4).unwrap();
1091
1092 ett.link(1, 2).unwrap();
1093 ett.link(3, 4).unwrap();
1094
1095 assert!(ett.connected(1, 2));
1097 assert!(ett.connected(3, 4));
1098
1099 assert!(!ett.connected(1, 3));
1101 assert!(!ett.connected(2, 4));
1102
1103 assert_eq!(ett.tree_size(1).unwrap(), 2);
1104 assert_eq!(ett.tree_size(3).unwrap(), 2);
1105 }
1106
1107 #[test]
1108 fn test_bulk_make_trees() {
1109 let mut ett = EulerTourTree::new();
1110 let vertices = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1111
1112 ett.bulk_make_trees(&vertices).unwrap();
1113
1114 assert_eq!(ett.len(), 10);
1115 for &v in &vertices {
1116 assert!(ett.first_occurrence.contains_key(&v));
1117 }
1118 }
1119
1120 #[test]
1121 fn test_bulk_update_values() {
1122 let mut ett = EulerTourTree::new();
1123 ett.make_tree(1).unwrap();
1124 ett.make_tree(2).unwrap();
1125 ett.make_tree(3).unwrap();
1126
1127 let updates = vec![(1, 10.0), (2, 20.0), (3, 30.0)];
1128 ett.bulk_update_values(&updates).unwrap();
1129
1130 assert_eq!(ett.nodes[0].value, 10.0);
1131 assert_eq!(ett.nodes[1].value, 20.0);
1132 assert_eq!(ett.nodes[2].value, 30.0);
1133 }
1134
1135 #[test]
1136 fn test_bulk_link() {
1137 let mut ett = EulerTourTree::new();
1138 for i in 1..=5 {
1139 ett.make_tree(i).unwrap();
1140 }
1141
1142 let edges = vec![(1, 2), (2, 3), (3, 4)];
1143 ett.bulk_link(&edges).unwrap();
1144
1145 assert!(ett.connected(1, 4));
1146 assert_eq!(ett.tree_size(1).unwrap(), 4);
1147 }
1148
1149 #[test]
1150 fn test_with_capacity() {
1151 let ett = EulerTourTree::with_seed_and_capacity(42, 100);
1152 assert_eq!(ett.nodes.capacity(), 100);
1153 }
1154
1155 #[test]
1156 fn test_lazy_propagation() {
1157 let mut ett = EulerTourTree::new();
1158 ett.make_tree(1).unwrap();
1159 ett.make_tree(2).unwrap();
1160 ett.make_tree(3).unwrap();
1161
1162 ett.link(1, 2).unwrap();
1163 ett.link(2, 3).unwrap();
1164
1165 let updates = vec![(1, 100.0), (2, 200.0), (3, 300.0)];
1167 ett.bulk_update_values(&updates).unwrap();
1168
1169 assert_eq!(ett.subtree_aggregate(1).unwrap(), 100.0);
1170 assert_eq!(ett.subtree_aggregate(2).unwrap(), 200.0);
1171 assert_eq!(ett.subtree_aggregate(3).unwrap(), 300.0);
1172 }
1173
1174 #[test]
1175 fn test_cut_edge() {
1176 let mut ett = EulerTourTree::new();
1177 ett.make_tree(1).unwrap();
1178 ett.make_tree(2).unwrap();
1179 ett.make_tree(3).unwrap();
1180
1181 ett.link(1, 2).unwrap();
1183 ett.link(2, 3).unwrap();
1184
1185 assert!(ett.connected(1, 3));
1187 assert_eq!(ett.tree_size(1).unwrap(), 3);
1188
1189 ett.cut(2, 3).unwrap();
1191
1192 assert!(ett.connected(1, 2));
1194 assert!(!ett.connected(1, 3));
1195 assert!(!ett.connected(2, 3));
1196 assert_eq!(ett.tree_size(1).unwrap(), 2);
1197 assert_eq!(ett.tree_size(3).unwrap(), 1);
1198 }
1199
1200 #[test]
1201 fn test_cut_and_relink() {
1202 let mut ett = EulerTourTree::new();
1203 for i in 1..=4 {
1204 ett.make_tree(i).unwrap();
1205 }
1206
1207 ett.link(1, 2).unwrap();
1209 ett.link(2, 3).unwrap();
1210 ett.link(3, 4).unwrap();
1211
1212 assert!(ett.connected(1, 4));
1213 assert_eq!(ett.tree_size(1).unwrap(), 4);
1214
1215 ett.cut(2, 3).unwrap();
1217
1218 assert!(ett.connected(1, 2));
1220 assert!(ett.connected(3, 4));
1221 assert!(!ett.connected(1, 3));
1222 assert!(!ett.connected(2, 4));
1223
1224 ett.link(1, 4).unwrap();
1226
1227 assert!(ett.connected(1, 3));
1229 assert_eq!(ett.tree_size(1).unwrap(), 4);
1230 }
1231
1232 #[test]
1233 fn test_cut_nonexistent_edge() {
1234 let mut ett = EulerTourTree::new();
1235 ett.make_tree(1).unwrap();
1236 ett.make_tree(2).unwrap();
1237
1238 assert!(matches!(
1240 ett.cut(1, 2),
1241 Err(MinCutError::EdgeNotFound(1, 2))
1242 ));
1243 }
1244}