1use crate::graph::Graph;
21
22#[derive(Clone, Copy)]
23enum DfsState {
24 Visit(usize), ProcessNeighbors(usize), Finalize(usize), }
28
29pub struct PathBasedScc {
30 scc: Vec<usize>,
31 stack: Vec<usize>, bounds: Vec<usize>, component: usize,
34}
35
36impl Default for PathBasedScc {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl PathBasedScc {
43 pub fn new() -> Self {
44 Self {
45 bounds: Vec::new(),
46 scc: Vec::new(),
47 stack: Vec::new(),
48 component: 0,
49 }
50 }
51
52 pub fn run<T>(&mut self, graph: &(impl Graph<T> + 'static)) -> Vec<usize> {
53 self.bounds = Vec::new();
55 self.scc.resize(graph.number_of_nodes(), usize::MAX);
56 self.stack = Vec::new();
57 self.component = graph.number_of_nodes();
58
59 for v in graph.node_range() {
61 if self.scc[v] == usize::MAX {
62 self.dfs_iterative(v, graph);
63 }
64 }
65
66 self.scc.clone()
67 }
68
69 fn dfs_iterative<T>(&mut self, start: usize, graph: &(impl Graph<T> + 'static)) {
70 let mut dfs_stack = vec![DfsState::Visit(start)];
71 let mut edge_indices = vec![0usize; graph.number_of_nodes()];
72
73 while let Some(state) = dfs_stack.pop() {
74 match state {
75 DfsState::Visit(v) => {
76 self.stack.push(v);
78 self.scc[v] = self.stack.len() - 1;
79 self.bounds.push(self.scc[v]);
80 dfs_stack.push(DfsState::ProcessNeighbors(v));
81 }
82
83 DfsState::ProcessNeighbors(v) => {
84 let edges: Vec<_> = graph.edge_range(v).collect();
85 if edge_indices[v] < edges.len() {
86 let e = edges[edge_indices[v]];
87 edge_indices[v] += 1;
88 dfs_stack.push(DfsState::ProcessNeighbors(v));
89
90 let w = graph.target(e);
91 if self.scc[w] == usize::MAX {
92 dfs_stack.push(DfsState::Visit(w));
93 } else {
94 while let Some(&bound) = self.bounds.last() {
96 if self.scc[w] < bound {
97 self.bounds.pop();
98 } else {
99 break;
100 }
101 }
102 }
103 } else {
104 dfs_stack.push(DfsState::Finalize(v));
105 }
106 }
107
108 DfsState::Finalize(v) => {
109 if Some(&self.scc[v]) == self.bounds.last() {
110 self.bounds.pop();
111 self.component -= 1;
112 while let Some(u) = self.stack.pop() {
113 self.scc[u] = self.component;
114 if u == v {
115 break;
116 }
117 }
118 }
119 }
120 }
121 }
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use crate::edge::InputEdge;
128 use crate::path_based_scc::PathBasedScc;
129 use crate::static_graph::StaticGraph;
130
131 #[test]
132 fn scc_wiki1() {
133 type Graph = StaticGraph<i32>;
134 let edges = vec![
135 InputEdge::new(0, 1, 3),
136 InputEdge::new(1, 2, 3),
137 InputEdge::new(1, 4, 1),
138 InputEdge::new(1, 5, 6),
139 InputEdge::new(2, 3, 2),
140 InputEdge::new(2, 6, 2),
141 InputEdge::new(3, 2, 2),
142 InputEdge::new(3, 7, 2),
143 InputEdge::new(4, 0, 2),
144 InputEdge::new(4, 5, 2),
145 InputEdge::new(5, 6, 2),
146 InputEdge::new(6, 5, 2),
147 InputEdge::new(7, 3, 2),
148 InputEdge::new(7, 6, 2),
149 ];
150 let graph = Graph::new(edges);
151
152 let mut scc = PathBasedScc::new();
153 assert_eq!(vec![5, 5, 6, 6, 5, 7, 7, 6], scc.run(&graph));
154 }
155
156 #[test]
157 fn geekforgeeks() {
158 type Graph = StaticGraph<i32>;
159 let edges = vec![
160 InputEdge::new(1, 0, 3),
161 InputEdge::new(0, 3, 3),
162 InputEdge::new(0, 2, 1),
163 InputEdge::new(2, 1, 6),
164 InputEdge::new(3, 4, 2),
165 ];
166 let graph = Graph::new(edges);
167
168 let mut scc = PathBasedScc::new();
169 assert_eq!(vec![2, 2, 2, 3, 4], scc.run(&graph));
170 }
171
172 #[test]
173 fn stanford2() {
174 type Graph = StaticGraph<i32>;
175 let edges = vec![
176 InputEdge::new(0, 6, 3),
177 InputEdge::new(6, 3, 3),
178 InputEdge::new(3, 0, 1),
179 InputEdge::new(6, 8, 6),
180 InputEdge::new(8, 5, 2),
181 InputEdge::new(5, 2, 2),
182 InputEdge::new(2, 8, 2),
183 InputEdge::new(5, 7, 2),
184 InputEdge::new(7, 1, 2),
185 InputEdge::new(4, 7, 2),
186 InputEdge::new(1, 4, 2),
187 ];
188 let graph = Graph::new(edges);
189
190 let mut scc = PathBasedScc::new();
191 assert_eq!(vec![6, 8, 7, 6, 8, 7, 6, 8, 7], scc.run(&graph));
192 }
193
194 #[test]
195 fn web1() {
196 type Graph = StaticGraph<i32>;
197 let edges = vec![
198 InputEdge::new(0, 1, 3),
199 InputEdge::new(1, 3, 3),
200 InputEdge::new(1, 4, 1),
201 InputEdge::new(1, 2, 6),
202 InputEdge::new(2, 5, 2),
203 InputEdge::new(4, 1, 2),
204 InputEdge::new(4, 5, 2),
205 InputEdge::new(4, 6, 2),
206 InputEdge::new(5, 7, 2),
207 InputEdge::new(6, 7, 2),
208 InputEdge::new(6, 8, 2),
209 InputEdge::new(7, 9, 2),
210 InputEdge::new(9, 10, 2),
211 InputEdge::new(10, 8, 2),
212 InputEdge::new(8, 11, 2),
213 InputEdge::new(11, 6, 2),
214 ];
215 let graph = Graph::new(edges);
216
217 let mut scc = PathBasedScc::default();
218 assert_eq!(
219 vec![6, 7, 9, 8, 7, 10, 11, 11, 11, 11, 11, 11],
220 scc.run(&graph)
221 );
222 }
223}