utils/
disjoint_set.rs

1//! Disjoint-set data structures.
2
3/// Disjoint-set union (DSU) data structure.
4///
5/// # Example
6/// ```
7/// # use utils::disjoint_set::Dsu;
8/// let mut dsu = Dsu::new(5);
9///
10/// for i in 0..5 {
11///     assert_eq!(dsu.find(i), i);
12///     assert_eq!(dsu.set_size(i), 1);
13/// }
14///
15/// assert!(dsu.union(0, 1));
16/// assert!(dsu.union(1, 2));
17/// assert!(!dsu.union(0, 2));
18/// assert!(dsu.union(3, 4));
19///
20/// assert_eq!(dsu.find(0), dsu.find(1));
21/// assert_eq!(dsu.find(0), dsu.find(2));
22/// assert_eq!(dsu.set_size(0), 3);
23///
24/// assert_eq!(dsu.find(3), dsu.find(4));
25/// assert_eq!(dsu.set_size(3), 2);
26/// assert_ne!(dsu.find(0), dsu.find(3));
27///
28/// assert!(dsu.union(1, 3));
29/// assert_eq!(dsu.set_size(0), 5);
30/// for i in 1..5 {
31///     assert_eq!(dsu.find(0), dsu.find(i));
32/// }
33/// ```
34#[derive(Debug)]
35pub struct Dsu {
36    parent: Vec<usize>,
37    size: Vec<usize>,
38}
39
40impl Dsu {
41    /// Creates a new disjoint-set union data structure with `n` elements.
42    #[must_use]
43    pub fn new(n: usize) -> Self {
44        Dsu {
45            parent: (0..n).collect(),
46            size: vec![1; n],
47        }
48    }
49
50    /// Find the root of the set containing the element at index `x`.
51    ///
52    /// This requires `&mut self` because it performs path compression, making later calls faster.
53    #[inline]
54    #[must_use]
55    pub fn find(&mut self, mut x: usize) -> usize {
56        let mut root = x;
57        while self.parent[root] != root {
58            root = self.parent[root];
59        }
60        while self.parent[x] != root {
61            (x, self.parent[x]) = (self.parent[x], root);
62        }
63        root
64    }
65
66    /// Merges the sets containing index `a` and `b`.
67    ///
68    /// Returns `true` if the sets were merged, `false` if they were already in the same set.
69    #[inline]
70    pub fn union(&mut self, a: usize, b: usize) -> bool {
71        let mut ra = self.find(a);
72        let mut rb = self.find(b);
73        if ra == rb {
74            return false;
75        }
76        if self.size[ra] < self.size[rb] {
77            (ra, rb) = (rb, ra);
78        }
79        self.parent[rb] = ra;
80        self.size[ra] += self.size[rb];
81        true
82    }
83
84    /// Returns the size of the set containing the element at index `x`.
85    ///
86    /// This requires `&mut self` because it performs path compression, making later calls faster.
87    #[inline]
88    #[must_use]
89    pub fn set_size(&mut self, x: usize) -> usize {
90        let root = self.find(x);
91        self.size[root]
92    }
93
94    /// Returns the size of the set with root `x`.
95    ///
96    /// This function will panic if `x` is not a root.
97    #[inline]
98    #[must_use]
99    pub fn root_size(&self, x: usize) -> usize {
100        assert_eq!(self.parent[x], x);
101        self.size[x]
102    }
103
104    /// Returns an iterator over the roots of the disjoint-set.
105    #[inline]
106    pub fn roots(&self) -> impl Iterator<Item = usize> + '_ {
107        (0..self.parent.len()).filter(|&x| self.parent[x] == x)
108    }
109}