ac_library/
scc.rs

1//! A `SccGraph` is a directed graph that calculates strongly connected components (SCC) in $O(|V| + |E|)$.
2
3use crate::internal_scc;
4
5/// An `SccGraph` is a directed graph that calculates strongly connected components (SCC) in $O(|V| + |E|)$.
6///
7/// # Example
8///
9/// ```
10/// use ac_library::SccGraph;
11/// use proconio::{input, source::once::OnceSource};
12///
13/// input! {
14///     from OnceSource::from(
15///         "5\n\
16///          5\n\
17///          0 1\n\
18///          1 2\n\
19///          2 0\n\
20///          0 3\n\
21///          3 4\n",
22///     ),
23///     n: usize,
24///     abs: [(usize, usize)],
25/// }
26///
27/// let mut graph = SccGraph::new(n);
28/// for (a, b) in abs {
29///     graph.add_edge(a, b);
30/// }
31///
32/// assert_eq!(graph.scc(), [&[0, 1, 2][..], &[3], &[4]]);
33/// ```
34#[derive(Clone, Debug)]
35pub struct SccGraph {
36    internal: internal_scc::SccGraph,
37}
38
39impl SccGraph {
40    /// Creates a new `SccGraph` with `n` vertices and `0` edges.
41    ///
42    /// # Constraints
43    ///
44    /// - $0 \leq n \leq 10^8$
45    ///
46    /// # Complexity
47    ///
48    /// - $O(n)$
49    pub fn new(n: usize) -> Self {
50        SccGraph {
51            internal: internal_scc::SccGraph::new(n),
52        }
53    }
54
55    /// Adds a directed edge from the vertex `from` to the vertex `to`.
56    ///
57    /// # Constraints
58    ///
59    /// - $0 \leq$ `from` $< n$
60    /// - $0 \leq$ `to` $< n$
61    ///
62    /// # Panics
63    ///
64    /// Panics if the above constraints are not satisfied.
65    ///
66    /// # Complexity
67    ///
68    /// - $O(1)$ amortized
69    pub fn add_edge(&mut self, from: usize, to: usize) {
70        let n = self.internal.num_vertices();
71        assert!(from < n);
72        assert!(to < n);
73        self.internal.add_edge(from, to);
74    }
75
76    /// Calculates the strongly connected components (SCC) of directed graphs in $O(|V| + |E|)$.
77    ///
78    /// Returns the list of the "list of the vertices" that satisfies the following.
79    ///
80    /// - Each vertex is in exactly one "list of the vertices".
81    /// - Each "list of the vertices" corresponds to the vertex set of a strongly connected component. The order of the vertices in the list is undefined.
82    /// - The list of "list of the vertices" are sorted in topological order, i.e., for two vertices $u$, $v$ in different strongly connected components, if there is a directed path from $u$ to $v$, the list containing $u$ appears earlier than the list containing $v$.
83    ///
84    /// # Complexity
85    ///
86    /// - $O(n + m)$ where $m$ is the number of added edges
87    pub fn scc(&self) -> Vec<Vec<usize>> {
88        self.internal.scc()
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn test_scc_simple() {
98        let mut graph = SccGraph::new(2);
99        graph.add_edge(0, 1);
100        graph.add_edge(1, 0);
101        let scc = graph.scc();
102        assert_eq!(scc.len(), 1);
103    }
104
105    #[test]
106    fn test_scc_self_loop() {
107        let mut graph = SccGraph::new(2);
108        graph.add_edge(0, 0);
109        graph.add_edge(0, 0);
110        graph.add_edge(1, 1);
111        let scc = graph.scc();
112        assert_eq!(scc.len(), 2);
113    }
114
115    #[test]
116    fn solve_alpc_g_sample1() {
117        // https://atcoder.jp/contests/practice2/tasks/practice2_g
118        let n: usize = 6;
119        let edges = vec![(1, 4), (5, 2), (3, 0), (5, 5), (4, 1), (0, 3), (4, 2)];
120
121        let mut graph = SccGraph::new(n);
122        for (u, v) in edges.into_iter() {
123            graph.add_edge(u, v);
124        }
125
126        let scc = graph.scc();
127        assert_eq!(scc, vec![vec![5], vec![1, 4], vec![2], vec![0, 3]]);
128    }
129}