strongly_connected_components/internal/
scc_decomposition.rs

1use crate::internal::node::Node;
2use crate::internal::scc::Scc;
3
4/// Represents the decomposition of a [`Graph`](crate::Graph) into
5/// [Strongly Connected Components](https://en.wikipedia.org/wiki/Strongly_connected_component)
6/// (SCC).
7pub struct SccDecomposition {
8    pub(super) nodes_to_sccs: Vec<usize>,
9    pub(super) sccs: Vec<Scc>,
10}
11
12impl SccDecomposition {
13    /// Returns the number of SCCs in the decomposition.
14    pub fn len(&self) -> usize {
15        self.sccs.len()
16    }
17
18    /// Returns `true` if there are no SCCs.
19    pub fn is_empty(&self) -> bool {
20        self.sccs.is_empty()
21    }
22
23    /// Returns the SCC containing the given node.
24    /// Each node of the [`Graph`](crate::Graph) will always
25    /// be assigned to exactly one SCC.
26    pub fn scc_of_node(&self, node: Node) -> &Scc {
27        assert!(node.id < self.nodes_to_sccs.len());
28        let scc_id = self.nodes_to_sccs[node.id];
29        assert!(scc_id < self.sccs.len());
30        &self.sccs[scc_id]
31    }
32
33    /// Returns an iterator over all SCCs in topological order.
34    /// If nodes `A` and `B` belong to different SCCs
35    /// and the graph has an edge `A->B`, then `B`'s SCC will appear before `A`'s SCC.
36    pub fn iter_sccs(&self) -> impl Iterator<Item = &Scc> {
37        self.sccs.iter()
38    }
39
40    /// Returns an iterator over all nodes in topological order.
41    /// If nodes `A` and `B` belong to different SCCs
42    /// and the graph has an edge `A->B`, then `B` will appear before `A`.
43    pub fn iter_nodes(&self) -> impl Iterator<Item = Node> + '_ {
44        self.sccs.iter().flat_map(|sccs| sccs.iter_nodes())
45    }
46}