contest_algorithms/graph/
connectivity.rs1use super::Graph;
3
4struct ConnectivityData {
7 time: usize,
8 vis: Box<[usize]>,
9 low: Box<[usize]>,
10 v_stack: Vec<usize>,
11 e_stack: Vec<usize>,
12}
13
14impl ConnectivityData {
15 fn new(num_v: usize) -> Self {
16 Self {
17 time: 0,
18 vis: vec![0; num_v].into_boxed_slice(),
19 low: vec![0; num_v].into_boxed_slice(),
20 v_stack: vec![],
21 e_stack: vec![],
22 }
23 }
24
25 fn visit(&mut self, u: usize) {
26 self.time += 1;
27 self.vis[u] = self.time;
28 self.low[u] = self.time;
29 self.v_stack.push(u);
30 }
31
32 fn lower(&mut self, u: usize, val: usize) {
33 if self.low[u] > val {
34 self.low[u] = val
35 }
36 }
37}
38
39pub struct ConnectivityGraph<'a> {
48 pub graph: &'a Graph,
50 pub cc: Vec<usize>,
52 pub vcc: Vec<usize>,
54 pub num_cc: usize,
56 pub num_vcc: usize,
58}
59
60impl<'a> ConnectivityGraph<'a> {
61 pub fn new(graph: &'a Graph, is_directed: bool) -> Self {
69 let mut connect = Self {
70 graph,
71 cc: vec![0; graph.num_v()],
72 vcc: vec![0; graph.num_e()],
73 num_cc: 0,
74 num_vcc: 0,
75 };
76 let mut data = ConnectivityData::new(graph.num_v());
77 for u in 0..graph.num_v() {
78 if data.vis[u] == 0 {
79 if is_directed {
80 connect.scc(&mut data, u);
81 } else {
82 connect.bcc(&mut data, u, graph.num_e() + 1);
83 }
84 }
85 }
86 connect
87 }
88
89 fn scc(&mut self, data: &mut ConnectivityData, u: usize) {
90 data.visit(u);
91 for (_, v) in self.graph.adj_list(u) {
92 if data.vis[v] == 0 {
93 self.scc(data, v);
94 }
95 if self.cc[v] == 0 {
96 data.lower(u, data.low[v]);
97 }
98 }
99 if data.vis[u] == data.low[u] {
100 self.num_cc += 1;
101 while let Some(v) = data.v_stack.pop() {
102 self.cc[v] = self.num_cc;
103 if v == u {
104 break;
105 }
106 }
107 }
108 }
109
110 pub fn two_sat_assign(&self) -> Option<Vec<bool>> {
113 (0..self.graph.num_v() / 2)
114 .map(|i| {
115 let scc_true = self.cc[2 * i];
116 let scc_false = self.cc[2 * i + 1];
117 if scc_true == scc_false {
118 None
119 } else {
120 Some(scc_true < scc_false)
121 }
122 })
123 .collect()
124 }
125
126 pub fn topological_sort(&self) -> Vec<usize> {
129 let mut vertices = (0..self.graph.num_v()).collect::<Vec<_>>();
130 vertices.sort_unstable_by_key(|&u| self.num_cc - self.cc[u]);
131 vertices
132 }
133
134 fn bcc(&mut self, data: &mut ConnectivityData, u: usize, par: usize) {
135 data.visit(u);
136 for (e, v) in self.graph.adj_list(u) {
137 if data.vis[v] == 0 {
138 data.e_stack.push(e);
139 self.bcc(data, v, e);
140 data.lower(u, data.low[v]);
141 if data.vis[u] <= data.low[v] {
142 self.num_vcc += 1;
144 while let Some(top_e) = data.e_stack.pop() {
145 self.vcc[top_e] = self.num_vcc;
146 self.vcc[top_e ^ 1] = self.num_vcc;
147 if e ^ top_e <= 1 {
148 break;
149 }
150 }
151 }
152 } else if data.vis[v] < data.vis[u] && e ^ par != 1 {
153 data.lower(u, data.vis[v]);
154 data.e_stack.push(e);
155 } else if v == u {
156 self.num_vcc += 1;
158 self.vcc[e] = self.num_vcc;
159 self.vcc[e ^ 1] = self.num_vcc;
160 }
161 }
162 if data.vis[u] == data.low[u] {
163 self.num_cc += 1;
165 while let Some(v) = data.v_stack.pop() {
166 self.cc[v] = self.num_cc;
167 if v == u {
168 break;
169 }
170 }
171 }
172 }
173
174 pub fn is_cut_vertex(&self, u: usize) -> bool {
176 if let Some(first_e) = self.graph.first[u] {
177 self.graph
178 .adj_list(u)
179 .any(|(e, _)| self.vcc[first_e] != self.vcc[e])
180 } else {
181 false
182 }
183 }
184
185 pub fn is_cut_edge(&self, e: usize) -> bool {
187 let u = self.graph.endp[e ^ 1];
188 let v = self.graph.endp[e];
189 self.cc[u] != self.cc[v]
190 }
191}
192
193#[cfg(test)]
194mod test {
195 use super::*;
196
197 #[test]
198 fn test_toposort() {
199 let mut graph = Graph::new(4, 5);
200 graph.add_edge(0, 0);
201 graph.add_edge(0, 2);
202 graph.add_edge(3, 2);
203 graph.add_edge(3, 1);
204 graph.add_edge(1, 0);
205
206 assert_eq!(
207 ConnectivityGraph::new(&graph, true).topological_sort(),
208 vec![3, 1, 0, 2]
209 );
210 }
211
212 #[test]
213 fn test_two_sat() {
214 let mut graph = Graph::new(6, 8);
215 let (x, y, z) = (0, 2, 4);
216
217 graph.add_two_sat_clause(x, z);
218 graph.add_two_sat_clause(y ^ 1, z ^ 1);
219 graph.add_two_sat_clause(y, y);
220 assert_eq!(
221 ConnectivityGraph::new(&graph, true).two_sat_assign(),
222 Some(vec![true, true, false])
223 );
224
225 graph.add_two_sat_clause(z, z);
226 assert_eq!(ConnectivityGraph::new(&graph, true).two_sat_assign(), None);
227 }
228
229 #[test]
230 fn test_biconnected() {
231 let mut graph = Graph::new(3, 6);
232 graph.add_undirected_edge(0, 1);
233 graph.add_undirected_edge(1, 2);
234 graph.add_undirected_edge(1, 2);
235
236 let cg = ConnectivityGraph::new(&graph, false);
237 let bridges = (0..graph.num_e())
238 .filter(|&e| cg.is_cut_edge(e))
239 .collect::<Vec<_>>();
240 let articulation_points = (0..graph.num_v())
241 .filter(|&u| cg.is_cut_vertex(u))
242 .collect::<Vec<_>>();
243
244 assert_eq!(bridges, vec![0, 1]);
245 assert_eq!(articulation_points, vec![1]);
246 }
247}