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.first_occurrence.get(&u)
213 .ok_or_else(|| MinCutError::InvalidVertex(u))?;
214 let v_root = *self.first_occurrence.get(&v)
215 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
216
217 if self.connected(u, v) {
219 return Err(MinCutError::EdgeExists(u, v));
220 }
221
222 self.reroot_internal(u)?;
224
225 let u_root = self.find_root_idx(u_idx)?;
227
228 let priority1 = self.rng.next();
230 let priority2 = self.rng.next();
231 let enter_v = self.allocate_node(v, priority1, 0.0);
232 let exit_v = self.allocate_node(u, priority2, 0.0);
233
234 self.edge_to_node.insert((u, v), enter_v);
236 self.enter_to_exit.insert(enter_v, exit_v);
237
238 let merged1 = self.merge(Some(u_root), Some(enter_v));
240 let merged2 = self.merge(merged1, Some(v_root));
241 let final_root = self.merge(merged2, Some(exit_v));
242
243 if let Some(root) = final_root {
245 let root_vertex = self.nodes[root].vertex;
246 self.update_root_mapping(root, root_vertex);
247 }
248
249 Ok(())
250 }
251
252 pub fn cut(&mut self, u: NodeId, v: NodeId) -> Result<()> {
257 let edge_node = self.edge_to_node.remove(&(u, v))
259 .or_else(|| self.edge_to_node.remove(&(v, u)))
260 .ok_or_else(|| MinCutError::EdgeNotFound(u, v))?;
261
262 self.reroot_internal(u)?;
264
265 let enter_v = edge_node;
267
268 let exit_u_idx = self.find_matching_exit(enter_v)?;
270
271 self.enter_to_exit.remove(&enter_v);
273
274 let pos1 = self.get_position(enter_v);
276 let pos2 = self.get_position(exit_u_idx);
277
278 let (start_pos, end_pos) = if pos1 < pos2 {
280 (pos1, pos2)
281 } else {
282 (pos2, pos1)
283 };
284
285 let root = self.find_root_idx(*self.first_occurrence.get(&u).unwrap())?;
287
288 let (left, rest) = self.split(root, start_pos);
291 if rest.is_none() {
292 return Err(MinCutError::InternalError("Split failed".to_string()));
293 }
294
295 let (enter_and_middle, right) = self.split(rest.unwrap(), end_pos - start_pos + 1);
296
297 let (enter_node, middle_and_exit) = self.split_first(enter_and_middle);
299
300 let (middle, exit_node) = self.split_last(middle_and_exit);
302
303 if let Some(idx) = enter_node {
305 self.free_node(idx);
306 }
307 if let Some(idx) = exit_node {
308 self.free_node(idx);
309 }
310
311 let u_tree = self.merge(left, right);
313
314 let v_tree = middle;
316
317 if let Some(root_idx) = u_tree {
319 let root_vertex = self.nodes[root_idx].vertex;
320 self.update_root_mapping(root_idx, root_vertex);
321 }
322 if let Some(root_idx) = v_tree {
323 let root_vertex = self.nodes[root_idx].vertex;
324 self.update_root_mapping(root_idx, root_vertex);
325 }
326
327 Ok(())
328 }
329
330 #[inline]
332 pub fn connected(&self, u: NodeId, v: NodeId) -> bool {
333 match (self.first_occurrence.get(&u), self.first_occurrence.get(&v)) {
334 (Some(&u_idx), Some(&v_idx)) => {
335 let u_root = self.find_root_idx(u_idx);
336 let v_root = self.find_root_idx(v_idx);
337 matches!((u_root, v_root), (Ok(ur), Ok(vr)) if ur == vr)
338 }
339 _ => false,
340 }
341 }
342
343 #[inline]
345 pub fn find_root(&self, v: NodeId) -> Result<NodeId> {
346 let v_idx = *self.first_occurrence.get(&v)
347 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
348 let root_idx = self.find_root_idx(v_idx)?;
349 Ok(self.nodes[root_idx].vertex)
350 }
351
352 #[inline]
354 pub fn tree_size(&self, v: NodeId) -> Result<usize> {
355 let v_idx = *self.first_occurrence.get(&v)
356 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
357 let root_idx = self.find_root_idx(v_idx)?;
358
359 let vertices = self.collect_vertices(root_idx);
361 Ok(vertices.len())
362 }
363
364 #[inline]
366 pub fn subtree_size(&self, v: NodeId) -> Result<usize> {
367 let first_idx = *self.first_occurrence.get(&v)
368 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
369 let last_idx = *self.last_occurrence.get(&v)
370 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
371
372 if first_idx == last_idx {
373 return Ok(1); }
375
376 let pos1 = self.get_position(first_idx);
378 let pos2 = self.get_position(last_idx);
379 let range_size = pos2.saturating_sub(pos1) + 1;
380
381 Ok((range_size + 1) / 2)
382 }
383
384 #[inline]
386 pub fn subtree_aggregate(&self, v: NodeId) -> Result<f64> {
387 let first_idx = *self.first_occurrence.get(&v)
388 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
389
390 Ok(self.nodes[first_idx].subtree_aggregate)
392 }
393
394 #[inline]
396 pub fn update_value(&mut self, v: NodeId, value: f64) -> Result<()> {
397 let first_idx = *self.first_occurrence.get(&v)
398 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
399
400 self.nodes[first_idx].value = value;
401 self.pull_up(first_idx);
402
403 Ok(())
404 }
405
406 pub fn reroot(&mut self, v: NodeId) -> Result<()> {
408 self.reroot_internal(v)
409 }
410
411 #[inline]
413 pub fn len(&self) -> usize {
414 self.first_occurrence.len()
415 }
416
417 #[inline]
419 pub fn is_empty(&self) -> bool {
420 self.first_occurrence.is_empty()
421 }
422
423 pub fn bulk_make_trees(&mut self, vertices: &[NodeId]) -> Result<()> {
432 let count = vertices.len();
434 self.nodes.reserve(count);
435 self.first_occurrence.reserve(count);
436 self.last_occurrence.reserve(count);
437 self.roots.reserve(count);
438
439 for &v in vertices {
440 if self.first_occurrence.contains_key(&v) {
441 return Err(self.vertex_exists_error(v));
442 }
443
444 let priority = self.rng.next();
445 let idx = self.allocate_node(v, priority, 0.0);
446
447 self.first_occurrence.insert(v, idx);
448 self.last_occurrence.insert(v, idx);
449 self.roots.insert(v, idx);
450 }
451
452 Ok(())
453 }
454
455 pub fn bulk_update_values(&mut self, updates: &[(NodeId, f64)]) -> Result<()> {
462 let mut affected_indices = Vec::with_capacity(updates.len());
464
465 for &(v, value) in updates {
466 let idx = *self.first_occurrence.get(&v)
467 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
468
469 self.nodes[idx].lazy_value = Some(value);
470 affected_indices.push(idx);
471 }
472
473 for &idx in &affected_indices {
475 self.push_down_lazy(idx);
476 self.pull_up(idx);
477 }
478
479 Ok(())
480 }
481
482 pub fn bulk_link(&mut self, edges: &[(NodeId, NodeId)]) -> Result<()> {
488 for &(u, v) in edges {
490 self.first_occurrence.get(&u)
491 .ok_or_else(|| MinCutError::InvalidVertex(u))?;
492 self.first_occurrence.get(&v)
493 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
494 }
495
496 for &(u, v) in edges {
498 self.link(u, v)?;
499 }
500
501 Ok(())
502 }
503
504 #[inline]
511 fn find_root_idx(&self, mut idx: usize) -> Result<usize> {
512 let mut visited = 0;
513 let max_depth = self.nodes.len() * 2; while let Some(parent) = self.nodes[idx].parent {
516 idx = parent;
517 visited += 1;
518 if visited > max_depth {
519 return Err(MinCutError::InternalError("Cycle detected in tree".to_string()));
520 }
521 }
522 Ok(idx)
523 }
524
525 fn reroot_internal(&mut self, v: NodeId) -> Result<()> {
527 let v_first = *self.first_occurrence.get(&v)
528 .ok_or_else(|| MinCutError::InvalidVertex(v))?;
529
530 let root = self.find_root_idx(v_first)?;
532
533 let pos = self.get_position(v_first);
535 if pos == 0 {
536 return Ok(());
537 }
538
539 let (left, right) = self.split(root, pos);
542
543 let new_root = self.merge(right, left);
545
546 if let Some(root_idx) = new_root {
548 let root_vertex = self.nodes[root_idx].vertex;
549 self.update_root_mapping(root_idx, root_vertex);
550 }
551
552 Ok(())
553 }
554
555 fn update_root_mapping(&mut self, root_idx: usize, _root_vertex: NodeId) {
557 let vertices = self.collect_vertices(root_idx);
559 for vertex in vertices {
560 self.roots.insert(vertex, root_idx);
561 }
562 }
563
564 fn collect_vertices(&self, idx: usize) -> Vec<NodeId> {
569 let estimated_size = self.nodes[idx].size / 2;
570 let mut vertices = Vec::with_capacity(estimated_size);
571 let mut visited = std::collections::HashSet::with_capacity(estimated_size);
572 self.collect_vertices_helper(idx, &mut vertices, &mut visited);
573 vertices
574 }
575
576 #[inline]
577 fn collect_vertices_helper(&self, idx: usize, vertices: &mut Vec<NodeId>, visited: &mut std::collections::HashSet<NodeId>) {
578 let node = &self.nodes[idx];
579 if visited.insert(node.vertex) {
580 vertices.push(node.vertex);
581 }
582
583 if let Some(left) = node.left {
584 self.collect_vertices_helper(left, vertices, visited);
585 }
586 if let Some(right) = node.right {
587 self.collect_vertices_helper(right, vertices, visited);
588 }
589 }
590
591 #[inline]
596 fn find_matching_exit(&self, enter_idx: usize) -> Result<usize> {
597 self.enter_to_exit
598 .get(&enter_idx)
599 .copied()
600 .ok_or_else(|| MinCutError::InternalError(
601 format!("No matching exit node found for enter index {}", enter_idx)
602 ))
603 }
604
605 #[inline]
613 fn split(&mut self, root: usize, pos: usize) -> (Option<usize>, Option<usize>) {
614 if pos == 0 {
615 return (None, Some(root));
616 }
617
618 self.push_down_lazy(root);
620
621 let left_size = self.nodes[root].left.map(|l| self.nodes[l].size).unwrap_or(0);
622
623 if pos <= left_size {
624 if let Some(left_child) = self.nodes[root].left {
626 let (split_left, split_right) = self.split(left_child, pos);
627 self.nodes[root].left = split_right;
628 if let Some(idx) = split_right {
629 self.nodes[idx].parent = Some(root);
630 }
631 self.pull_up(root);
632
633 if let Some(idx) = split_left {
634 self.nodes[idx].parent = None;
635 }
636
637 (split_left, Some(root))
638 } else {
639 (None, Some(root))
640 }
641 } else {
642 let right_pos = pos - left_size - 1;
644 if let Some(right_child) = self.nodes[root].right {
645 let (split_left, split_right) = self.split(right_child, right_pos);
646 self.nodes[root].right = split_left;
647 if let Some(idx) = split_left {
648 self.nodes[idx].parent = Some(root);
649 }
650 self.pull_up(root);
651
652 if let Some(idx) = split_right {
653 self.nodes[idx].parent = None;
654 }
655
656 (Some(root), split_right)
657 } else {
658 (Some(root), None)
659 }
660 }
661 }
662
663 #[inline]
670 fn merge(&mut self, left: Option<usize>, right: Option<usize>) -> Option<usize> {
671 match (left, right) {
672 (None, right) => right,
673 (left, None) => left,
674 (Some(l), Some(r)) => {
675 self.push_down_lazy(l);
677 self.push_down_lazy(r);
678
679 if self.nodes[l].priority > self.nodes[r].priority {
681 let new_right = self.merge(self.nodes[l].right, Some(r));
683 self.nodes[l].right = new_right;
684 if let Some(idx) = new_right {
685 self.nodes[idx].parent = Some(l);
686 }
687 self.nodes[l].parent = None;
688 self.pull_up(l);
689 Some(l)
690 } else {
691 let new_left = self.merge(Some(l), self.nodes[r].left);
693 self.nodes[r].left = new_left;
694 if let Some(idx) = new_left {
695 self.nodes[idx].parent = Some(r);
696 }
697 self.nodes[r].parent = None;
698 self.pull_up(r);
699 Some(r)
700 }
701 }
702 }
703 }
704
705 #[inline]
707 fn split_first(&mut self, root: Option<usize>) -> (Option<usize>, Option<usize>) {
708 match root {
709 None => (None, None),
710 Some(idx) => {
711 let (first, rest) = self.split(idx, 1);
712 (first, rest)
713 }
714 }
715 }
716
717 #[inline]
719 fn split_last(&mut self, root: Option<usize>) -> (Option<usize>, Option<usize>) {
720 match root {
721 None => (None, None),
722 Some(idx) => {
723 let size = self.nodes[idx].size;
724 if size == 0 {
725 return (None, None);
726 }
727 let (rest, last) = self.split(idx, size - 1);
728 (rest, last)
729 }
730 }
731 }
732
733 #[inline]
738 fn allocate_node(&mut self, vertex: NodeId, priority: u64, value: f64) -> usize {
739 if let Some(idx) = self.free_list.pop() {
740 self.nodes[idx] = TreapNode::new(vertex, priority, value);
741 idx
742 } else {
743 let idx = self.nodes.len();
744 self.nodes.push(TreapNode::new(vertex, priority, value));
745 idx
746 }
747 }
748
749 #[inline]
751 fn free_node(&mut self, idx: usize) {
752 self.nodes[idx].left = None;
754 self.nodes[idx].right = None;
755 self.nodes[idx].parent = None;
756 self.nodes[idx].lazy_value = None;
757 self.free_list.push(idx);
758 }
759
760 #[inline(always)]
766 fn push_down_lazy(&mut self, idx: usize) {
767 if let Some(lazy_val) = self.nodes[idx].lazy_value.take() {
768 self.nodes[idx].value = lazy_val;
770
771 if let Some(left) = self.nodes[idx].left {
773 self.nodes[left].lazy_value = Some(lazy_val);
774 }
775 if let Some(right) = self.nodes[idx].right {
776 self.nodes[right].lazy_value = Some(lazy_val);
777 }
778
779 self.pull_up(idx);
781 }
782 }
783
784 #[inline(always)]
789 fn pull_up(&mut self, idx: usize) {
790 let mut size = 1;
791 let mut aggregate = self.nodes[idx].value;
792
793 if let Some(left) = self.nodes[idx].left {
794 size += self.nodes[left].size;
795 aggregate += self.nodes[left].subtree_aggregate;
796 }
797
798 if let Some(right) = self.nodes[idx].right {
799 size += self.nodes[right].size;
800 aggregate += self.nodes[right].subtree_aggregate;
801 }
802
803 self.nodes[idx].size = size;
804 self.nodes[idx].subtree_aggregate = aggregate;
805 }
806
807 #[inline]
812 fn get_position(&self, idx: usize) -> usize {
813 let mut pos = self.nodes[idx].left.map(|l| self.nodes[l].size).unwrap_or(0);
814 let mut current = idx;
815
816 while let Some(parent) = self.nodes[current].parent {
817 if self.nodes[parent].right == Some(current) {
818 pos += 1;
820 if let Some(left) = self.nodes[parent].left {
821 pos += self.nodes[left].size;
822 }
823 }
824 current = parent;
825 }
826
827 pos
828 }
829}
830
831impl Default for EulerTourTree {
832 fn default() -> Self {
833 Self::new()
834 }
835}
836
837#[cfg(test)]
838mod tests {
839 use super::*;
840
841 #[test]
842 fn test_make_tree() {
843 let mut ett = EulerTourTree::new();
844 assert!(ett.make_tree(1).is_ok());
845 assert!(ett.make_tree(2).is_ok());
846 assert_eq!(ett.len(), 2);
847 }
848
849 #[test]
850 fn test_singleton_tree() {
851 let mut ett = EulerTourTree::new();
852 ett.make_tree(1).unwrap();
853
854 assert_eq!(ett.tree_size(1).unwrap(), 1);
855 assert_eq!(ett.subtree_size(1).unwrap(), 1);
856 assert!(ett.connected(1, 1));
857 }
858
859 #[test]
860 fn test_link_two_vertices() {
861 let mut ett = EulerTourTree::new();
862 ett.make_tree(1).unwrap();
863 ett.make_tree(2).unwrap();
864
865 assert!(!ett.connected(1, 2));
866
867 ett.link(1, 2).unwrap();
868
869 assert!(ett.connected(1, 2));
870 assert_eq!(ett.tree_size(1).unwrap(), 2);
871 assert_eq!(ett.tree_size(2).unwrap(), 2);
872 }
873
874 #[test]
875 fn test_link_multiple_vertices() {
876 let mut ett = EulerTourTree::new();
877
878 for i in 1..=5 {
879 ett.make_tree(i).unwrap();
880 }
881
882 ett.link(1, 2).unwrap();
884 ett.link(2, 3).unwrap();
885 ett.link(3, 4).unwrap();
886 ett.link(4, 5).unwrap();
887
888 for i in 1..=5 {
890 for j in 1..=5 {
891 assert!(ett.connected(i, j));
892 }
893 }
894
895 assert_eq!(ett.tree_size(1).unwrap(), 5);
896 }
897
898 #[test]
899 fn test_update_value() {
900 let mut ett = EulerTourTree::new();
901 ett.make_tree(1).unwrap();
902
903 ett.update_value(1, 10.0).unwrap();
904 assert_eq!(ett.subtree_aggregate(1).unwrap(), 10.0);
905
906 ett.update_value(1, 25.5).unwrap();
907 assert_eq!(ett.subtree_aggregate(1).unwrap(), 25.5);
908 }
909
910 #[test]
911 fn test_reroot() {
912 let mut ett = EulerTourTree::new();
913 ett.make_tree(1).unwrap();
914 ett.make_tree(2).unwrap();
915 ett.make_tree(3).unwrap();
916
917 ett.link(1, 2).unwrap();
918 ett.link(1, 3).unwrap();
919
920 assert!(ett.connected(1, 2));
922 assert!(ett.connected(2, 3));
923 assert_eq!(ett.tree_size(1).unwrap(), 3);
924
925 ett.reroot(2).unwrap();
927
928 assert!(ett.connected(1, 2));
930 assert!(ett.connected(2, 3));
931 assert_eq!(ett.tree_size(2).unwrap(), 3);
932 }
933
934 #[test]
935 fn test_invalid_vertex() {
936 let ett = EulerTourTree::new();
937
938 assert!(matches!(
939 ett.find_root(999),
940 Err(MinCutError::InvalidVertex(999))
941 ));
942
943 assert!(!ett.connected(1, 2));
944 }
945
946 #[test]
947 fn test_edge_already_exists() {
948 let mut ett = EulerTourTree::new();
949 ett.make_tree(1).unwrap();
950 ett.make_tree(2).unwrap();
951
952 ett.link(1, 2).unwrap();
953
954 assert!(matches!(
956 ett.link(1, 2),
957 Err(MinCutError::EdgeExists(1, 2))
958 ));
959 }
960
961 #[test]
962 fn test_split_and_merge() {
963 let mut ett = EulerTourTree::new();
964 ett.make_tree(1).unwrap();
965 ett.make_tree(2).unwrap();
966 ett.make_tree(3).unwrap();
967
968 ett.link(1, 2).unwrap();
969 ett.link(2, 3).unwrap();
970
971 assert!(ett.connected(1, 3));
973 assert_eq!(ett.tree_size(1).unwrap(), 3);
974 }
975
976 #[test]
977 fn test_tree_size_updates() {
978 let mut ett = EulerTourTree::new();
979
980 for i in 1..=10 {
981 ett.make_tree(i).unwrap();
982 }
983
984 for i in 2..=10 {
986 ett.link(1, i).unwrap();
987 }
988
989 assert_eq!(ett.tree_size(1).unwrap(), 10);
990 assert_eq!(ett.tree_size(5).unwrap(), 10);
991 }
992
993 #[test]
994 fn test_empty_tree() {
995 let ett = EulerTourTree::new();
996 assert!(ett.is_empty());
997 assert_eq!(ett.len(), 0);
998 }
999
1000 #[test]
1001 fn test_subtree_aggregate_simple() {
1002 let mut ett = EulerTourTree::new();
1003 ett.make_tree(1).unwrap();
1004 ett.make_tree(2).unwrap();
1005
1006 ett.update_value(1, 5.0).unwrap();
1007 ett.update_value(2, 3.0).unwrap();
1008
1009 assert_eq!(ett.subtree_aggregate(1).unwrap(), 5.0);
1010 assert_eq!(ett.subtree_aggregate(2).unwrap(), 3.0);
1011 }
1012
1013 #[test]
1014 fn test_reproducible_with_seed() {
1015 let mut ett1 = EulerTourTree::with_seed(12345);
1016 let mut ett2 = EulerTourTree::with_seed(12345);
1017
1018 for i in 1..=5 {
1019 ett1.make_tree(i).unwrap();
1020 ett2.make_tree(i).unwrap();
1021 }
1022
1023 ett1.link(1, 2).unwrap();
1024 ett2.link(1, 2).unwrap();
1025
1026 assert_eq!(ett1.tree_size(1).unwrap(), ett2.tree_size(1).unwrap());
1027 }
1028
1029 #[test]
1030 fn test_large_tree() {
1031 let mut ett = EulerTourTree::new();
1032 let n = 100;
1033
1034 for i in 0..n {
1035 ett.make_tree(i).unwrap();
1036 }
1037
1038 for i in 0..n-1 {
1040 ett.link(i, i + 1).unwrap();
1041 }
1042
1043 assert_eq!(ett.tree_size(0).unwrap(), n as usize);
1044 assert_eq!(ett.tree_size(n - 1).unwrap(), n as usize);
1045 assert!(ett.connected(0, n - 1));
1046 }
1047
1048 #[test]
1049 fn test_multiple_trees() {
1050 let mut ett = EulerTourTree::new();
1051
1052 ett.make_tree(1).unwrap();
1054 ett.make_tree(2).unwrap();
1055 ett.make_tree(3).unwrap();
1056 ett.make_tree(4).unwrap();
1057
1058 ett.link(1, 2).unwrap();
1059 ett.link(3, 4).unwrap();
1060
1061 assert!(ett.connected(1, 2));
1063 assert!(ett.connected(3, 4));
1064
1065 assert!(!ett.connected(1, 3));
1067 assert!(!ett.connected(2, 4));
1068
1069 assert_eq!(ett.tree_size(1).unwrap(), 2);
1070 assert_eq!(ett.tree_size(3).unwrap(), 2);
1071 }
1072
1073 #[test]
1074 fn test_bulk_make_trees() {
1075 let mut ett = EulerTourTree::new();
1076 let vertices = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
1077
1078 ett.bulk_make_trees(&vertices).unwrap();
1079
1080 assert_eq!(ett.len(), 10);
1081 for &v in &vertices {
1082 assert!(ett.first_occurrence.contains_key(&v));
1083 }
1084 }
1085
1086 #[test]
1087 fn test_bulk_update_values() {
1088 let mut ett = EulerTourTree::new();
1089 ett.make_tree(1).unwrap();
1090 ett.make_tree(2).unwrap();
1091 ett.make_tree(3).unwrap();
1092
1093 let updates = vec![(1, 10.0), (2, 20.0), (3, 30.0)];
1094 ett.bulk_update_values(&updates).unwrap();
1095
1096 assert_eq!(ett.nodes[0].value, 10.0);
1097 assert_eq!(ett.nodes[1].value, 20.0);
1098 assert_eq!(ett.nodes[2].value, 30.0);
1099 }
1100
1101 #[test]
1102 fn test_bulk_link() {
1103 let mut ett = EulerTourTree::new();
1104 for i in 1..=5 {
1105 ett.make_tree(i).unwrap();
1106 }
1107
1108 let edges = vec![(1, 2), (2, 3), (3, 4)];
1109 ett.bulk_link(&edges).unwrap();
1110
1111 assert!(ett.connected(1, 4));
1112 assert_eq!(ett.tree_size(1).unwrap(), 4);
1113 }
1114
1115 #[test]
1116 fn test_with_capacity() {
1117 let ett = EulerTourTree::with_seed_and_capacity(42, 100);
1118 assert_eq!(ett.nodes.capacity(), 100);
1119 }
1120
1121 #[test]
1122 fn test_lazy_propagation() {
1123 let mut ett = EulerTourTree::new();
1124 ett.make_tree(1).unwrap();
1125 ett.make_tree(2).unwrap();
1126 ett.make_tree(3).unwrap();
1127
1128 ett.link(1, 2).unwrap();
1129 ett.link(2, 3).unwrap();
1130
1131 let updates = vec![(1, 100.0), (2, 200.0), (3, 300.0)];
1133 ett.bulk_update_values(&updates).unwrap();
1134
1135 assert_eq!(ett.subtree_aggregate(1).unwrap(), 100.0);
1136 assert_eq!(ett.subtree_aggregate(2).unwrap(), 200.0);
1137 assert_eq!(ett.subtree_aggregate(3).unwrap(), 300.0);
1138 }
1139
1140 #[test]
1141 fn test_cut_edge() {
1142 let mut ett = EulerTourTree::new();
1143 ett.make_tree(1).unwrap();
1144 ett.make_tree(2).unwrap();
1145 ett.make_tree(3).unwrap();
1146
1147 ett.link(1, 2).unwrap();
1149 ett.link(2, 3).unwrap();
1150
1151 assert!(ett.connected(1, 3));
1153 assert_eq!(ett.tree_size(1).unwrap(), 3);
1154
1155 ett.cut(2, 3).unwrap();
1157
1158 assert!(ett.connected(1, 2));
1160 assert!(!ett.connected(1, 3));
1161 assert!(!ett.connected(2, 3));
1162 assert_eq!(ett.tree_size(1).unwrap(), 2);
1163 assert_eq!(ett.tree_size(3).unwrap(), 1);
1164 }
1165
1166 #[test]
1167 fn test_cut_and_relink() {
1168 let mut ett = EulerTourTree::new();
1169 for i in 1..=4 {
1170 ett.make_tree(i).unwrap();
1171 }
1172
1173 ett.link(1, 2).unwrap();
1175 ett.link(2, 3).unwrap();
1176 ett.link(3, 4).unwrap();
1177
1178 assert!(ett.connected(1, 4));
1179 assert_eq!(ett.tree_size(1).unwrap(), 4);
1180
1181 ett.cut(2, 3).unwrap();
1183
1184 assert!(ett.connected(1, 2));
1186 assert!(ett.connected(3, 4));
1187 assert!(!ett.connected(1, 3));
1188 assert!(!ett.connected(2, 4));
1189
1190 ett.link(1, 4).unwrap();
1192
1193 assert!(ett.connected(1, 3));
1195 assert_eq!(ett.tree_size(1).unwrap(), 4);
1196 }
1197
1198 #[test]
1199 fn test_cut_nonexistent_edge() {
1200 let mut ett = EulerTourTree::new();
1201 ett.make_tree(1).unwrap();
1202 ett.make_tree(2).unwrap();
1203
1204 assert!(matches!(
1206 ett.cut(1, 2),
1207 Err(MinCutError::EdgeNotFound(1, 2))
1208 ));
1209 }
1210}