competitive_library/graph/
strongly_connected_component.rs1#[derive(Debug)]
2enum Vertex {
3 In(usize),
4 Out(usize),
5}
6
7pub fn decompose(e: &[Vec<usize>]) -> Vec<Vec<usize>> {
8 let mut seen = vec![false; e.len()];
9
10 let mut stack = vec![];
11 let mut nodes = Vec::with_capacity(e.len());
12 for i in 0..e.len() {
13 if seen[i] {
14 continue;
15 }
16 stack.push(Vertex::In(i));
17
18 while let Some(vertex) = stack.pop() {
19 if let Vertex::In(v) = vertex {
20 if seen[v] {
21 continue;
22 }
23 stack.push(Vertex::Out(v));
24 seen[v] = true;
25 for &to in e[v].iter() {
26 stack.push(Vertex::In(to));
27 }
28 } else if let Vertex::Out(v) = vertex {
29 nodes.push(v);
30 }
31 }
32 }
33 let mut reverse_edge = vec![vec![]; e.len()];
34 for i in 0..e.len() {
35 for j in 0..e[i].len() {
36 reverse_edge[e[i][j]].push(i);
37 }
38 }
39
40 let mut components = vec![];
41 let mut back_stack = vec![];
42 let mut back_seen = vec![false; e.len()];
43 while let Some(v) = nodes.pop() {
44 if back_seen[v] {
45 continue;
46 }
47 let mut scc = vec![];
48 back_stack.push(v);
49 back_seen[v] = true;
50
51 while let Some(v) = back_stack.pop() {
52 for &to in reverse_edge[v].iter() {
53 if back_seen[to] {
54 continue;
55 }
56 back_stack.push(to);
57 back_seen[to] = true;
58 }
59
60 scc.push(v);
61 }
62 components.push(scc);
63 }
64 components
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70 #[test]
71 fn test_scc() {
72 let n = 6;
73 let v = [(1, 4), (5, 2), (3, 0), (5, 5), (4, 1), (0, 3), (4, 2)];
74 let mut e = vec![vec![]; n];
75 for &(v, u) in v.iter() {
76 e[v].push(u);
77 }
78 let a = decompose(&e);
79 assertvv(&a, &[vec![5], vec![1, 4], vec![2], vec![0, 3]]);
80 }
81 #[test]
82 fn test_scc2() {
83 let n = 7;
84 let v = [
85 (0, 2),
86 (1, 2),
87 (2, 3),
88 (3, 2),
89 (3, 4),
90 (4, 5),
91 (5, 6),
92 (6, 4),
93 ];
94 let mut e = vec![vec![]; n];
95 for &(v, u) in v.iter() {
96 e[v].push(u);
97 }
98 let a = decompose(&e);
99 dbg!(&a);
100 assertvv(&a, &[vec![0], vec![1], vec![3, 2], vec![5, 6, 4]]);
101 }
102
103 #[test]
104 fn test_scc3() {
105 let n = 11;
106 let v = vec![
107 (0, 1),
108 (1, 2),
109 (1, 10),
110 (2, 0),
111 (2, 3),
112 (3, 4),
113 (4, 5),
114 (4, 10),
115 (5, 6),
116 (6, 3),
117 (7, 8),
118 (7, 9),
119 (8, 10),
120 (9, 7),
121 (9, 7),
122 (9, 7),
123 (9, 7),
124 (10, 7),
125 ];
126 let mut e = vec![vec![]; n];
127 for &(v, u) in v.iter() {
128 e[v].push(u);
129 }
130 let a = decompose(&e);
131 dbg!(&a);
132 assertvv(&a, &[vec![0, 1, 2], vec![3, 4, 5, 6], vec![7, 8, 9, 10]]);
133 }
134 #[test]
135 fn test_scc4() {
136 let n = 5;
137 let v = [(0, 1), (0, 2), (2, 3), (3, 4)];
138 let mut e = vec![vec![]; n];
139 for &(v, u) in v.iter() {
140 e[v].push(u);
141 }
142 let a = decompose(&e);
143 dbg!(&a);
144 assertvv(&a, &[vec![0], vec![1], vec![2], vec![3], vec![4]]);
145 }
146 #[test]
147 fn test_scc5() {
148 let n = 5;
149 let v = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 0)];
150 let mut e = vec![vec![]; n];
151 for &(v, u) in v.iter() {
152 e[v].push(u);
153 }
154 let a = decompose(&e);
155 dbg!(&a);
156 assertvv(&a, &[vec![0, 1, 2, 3, 4]]);
157 }
158 #[test]
159 fn test_scc6() {
160 let n = 6;
161 let v = [(0, 1), (1, 2), (2, 0), (0, 3), (3, 4), (4, 0)];
162 let mut e = vec![vec![]; n];
163 for &(v, u) in v.iter() {
164 e[v].push(u);
165 }
166 let a = decompose(&e);
167 dbg!(&a);
168 assertvv(&a, &[vec![0, 1, 2, 3, 4], vec![5]]);
169 }
170 use std::collections::HashSet;
171 fn assertvv(a: &[Vec<usize>], b: &[Vec<usize>]) -> Option<()> {
172 assert_eq!(a.len(), b.len());
173 let mut a = convert(a);
174 let mut b = convert(b);
175
176 for i in a.iter_mut() {
177 for j in b.iter_mut() {
178 if j.is_none() {
179 continue;
180 }
181 if i.as_ref()?.eq(j.as_ref()?) {
182 i.take();
183 j.take();
184 break;
185 }
186 }
187 assert!(i.is_none());
188 }
189 Some(())
190 }
191 fn convert(a: &[Vec<usize>]) -> Vec<Option<HashSet<usize>>> {
192 a.iter()
193 .map(|x| Some(x.iter().cloned().collect::<HashSet<_>>()))
194 .collect::<Vec<_>>()
195 }
196}