strongly_connected_components/internal/graph.rs
1use crate::internal::node::Node;
2use crate::internal::scc_decomposition::SccDecomposition;
3use crate::internal::tarjan_algorithm::TarjanAlgorithm;
4
5/// Represents the graph on which SCC decomposition will be done.
6/// Consists of [`Node`]s, connected by directed edges.
7///
8/// ```
9/// # use strongly_connected_components::Graph;
10/// let mut graph = Graph::new();
11/// let v0 = graph.new_node();
12/// let v1 = graph.new_node();
13/// let v2 = graph.new_node();
14/// let v3 = graph.new_node();
15/// graph.new_edge(v0, v1);
16/// graph.new_edge(v1, v3);
17/// graph.new_edge(v1, v1);
18/// // Graph looks like this:
19/// // ┌───┐ ┌───┐ ┌───┐ ┌───┐
20/// // │ 0 ├─►│ 1 ├─►│ 3 │ │ 2 │
21/// // └───┘ └▲─┬┘ └───┘ └───┘
22/// // └─┘
23/// ```
24#[derive(Clone, Default)]
25pub struct Graph {
26 pub(super) edges: Vec<Vec<usize>>,
27}
28
29impl Graph {
30 /// Creates an empty graph with no nodes and no edges.
31 /// [`Node`]s can be added by calling [`Graph::new_node`].
32 /// Edges can be added by calling [`Graph::new_edge`].
33 pub fn new() -> Self {
34 Self { edges: Vec::new() }
35 }
36
37 /// Creates a new node of the graph with no incoming/outgoing edges.
38 /// Edges can be added by calling [`Graph::new_edge`].
39 pub fn new_node(&mut self) -> Node {
40 let node = Node {
41 id: self.edges.len(),
42 };
43 self.edges.push(Vec::new());
44 node
45 }
46
47 /// Creates a new directed edge between two nodes.
48 pub fn new_edge(&mut self, from: Node, to: Node) {
49 assert!(from.id < self.edges.len());
50 assert!(to.id < self.edges.len());
51 self.edges[from.id].push(to.id);
52 }
53
54 /// Computes the Strongly Connected Components decomposition of this graph.
55 /// Uses [Tarjan's algorithm](https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm)
56 /// which runs in O(|N| + |E|) time and uses O(|N| + |E|) memory.
57 pub fn find_sccs(&self) -> SccDecomposition {
58 TarjanAlgorithm::new(self).solve()
59 }
60
61 /// Returns the number of nodes in this graph.
62 pub fn len(&self) -> usize {
63 self.edges.len()
64 }
65
66 /// Returns `true` if the graph has no nodes.
67 pub fn is_empty(&self) -> bool {
68 self.edges.is_empty()
69 }
70
71 /// Iterates over all nodes that belong to this graph, in no particular order.
72 pub fn iter_nodes(&self) -> impl Iterator<Item = Node> {
73 (0..self.edges.len()).map(|id| Node { id })
74 }
75
76 /// Iterates over all successors of the given node, in no particular order.
77 pub fn iter_successors(&self, node: Node) -> impl Iterator<Item = Node> {
78 assert!(node.id < self.edges.len());
79 self.edges[node.id].iter().copied().map(|id| Node { id })
80 }
81}