1use std::{cmp::min, marker::PhantomData};
2
3use magnitude::Magnitude;
4
5use crate::{
6 graph::{Edge, UndirectedEdge},
7 provide::{Edges, Graph, IdMap, Vertices},
8};
9
10pub struct VertexEdgeCut<'a, W, E: Edge<W>> {
49 is_visited: Vec<bool>,
50 depth_of: Vec<Magnitude<usize>>,
51 low_of: Vec<Magnitude<usize>>,
52 parent_of: Vec<Magnitude<usize>>,
53 id_map: IdMap,
54 cut_vertices: Vec<usize>,
55 cut_edges: Vec<(usize, usize, &'a E)>,
56
57 phantom_w: PhantomData<W>,
58}
59
60impl<'a, W, E: Edge<W>> VertexEdgeCut<'a, W, E> {
61 pub fn init<G>(graph: &G) -> Self
63 where
64 G: Vertices + Edges<W, E> + Graph<W, E, UndirectedEdge>,
65 {
66 let vertex_count = graph.vertex_count();
67
68 VertexEdgeCut {
69 is_visited: vec![false; vertex_count],
70 depth_of: vec![Magnitude::PosInfinite; vertex_count],
71 low_of: vec![Magnitude::PosInfinite; vertex_count],
72 parent_of: vec![Magnitude::PosInfinite; vertex_count],
73 id_map: graph.continuos_id_map(),
74 cut_vertices: vec![],
75 cut_edges: vec![],
76
77 phantom_w: PhantomData,
78 }
79 }
80
81 pub fn execute<G>(mut self, graph: &'a G) -> (Vec<usize>, Vec<(usize, usize, &E)>)
91 where
92 G: Vertices + Edges<W, E> + Graph<W, E, UndirectedEdge>,
93 {
94 if !self.is_visited.is_empty() {
95 self.find_cut_vertices(graph, 0, 0.into());
96 }
97
98 (self.cut_vertices, self.cut_edges)
99 }
100
101 fn find_cut_vertices<G>(&mut self, graph: &'a G, virt_id: usize, depth: Magnitude<usize>)
102 where
103 G: Vertices + Edges<W, E>,
104 {
105 let real_id = self.id_map.real_id_of(virt_id);
106
107 let mut child_count = 0;
108 let mut is_vertex_cut = false;
109 self.is_visited[virt_id] = true;
110 self.depth_of[virt_id] = depth;
111 self.low_of[virt_id] = depth;
112
113 for (n_real_id, edge) in graph.edges_from_unchecked(real_id) {
114 let n_virt_id = self.id_map.virt_id_of(n_real_id);
115
116 if !self.is_visited[n_virt_id] {
117 self.parent_of[n_virt_id] = virt_id.into();
118 self.find_cut_vertices(graph, n_virt_id, depth + 1.into());
119 child_count += 1;
120 is_vertex_cut = self.low_of[n_virt_id] >= self.depth_of[virt_id];
121 if self.low_of[n_virt_id] > self.depth_of[virt_id] {
122 self.cut_edges.push((virt_id, n_real_id, edge));
123 }
124 self.low_of[virt_id] = min(self.low_of[virt_id], self.low_of[n_virt_id]);
125 } else if self.parent_of[virt_id] != n_virt_id.into() {
126 self.low_of[virt_id] = min(self.low_of[virt_id], self.depth_of[n_virt_id]);
127 }
128 }
129
130 if (self.parent_of[virt_id].is_finite() && is_vertex_cut)
131 || (!self.parent_of[virt_id].is_finite() && child_count > 1)
132 {
133 self.cut_vertices.push(virt_id);
134 }
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use crate::graph::MatGraph;
142 use crate::storage::Mat;
143
144 #[test]
145 fn empty_graph() {
146 let graph = MatGraph::init(Mat::<usize>::init());
147
148 let (cut_vertices, cut_edges) = VertexEdgeCut::init(&graph).execute(&graph);
149
150 assert!(cut_vertices.is_empty());
151 assert!(cut_edges.is_empty());
152 }
153
154 #[test]
155 fn one_vertex_graph() {
156 let mut graph = MatGraph::init(Mat::<usize>::init());
157 graph.add_vertex();
158
159 let (cut_vertices, cut_edges) = VertexEdgeCut::init(&graph).execute(&graph);
160
161 assert!(cut_vertices.is_empty());
162 assert!(cut_edges.is_empty());
163 }
164
165 #[test]
166 fn two_vertex_graph() {
167 let mut graph = MatGraph::init(Mat::<usize>::init());
169 let a = graph.add_vertex();
170 let b = graph.add_vertex();
171 let ab = graph.add_edge_unchecked(a, b, 1.into());
172
173 let (cut_vertices, cut_edges) = VertexEdgeCut::init(&graph).execute(&graph);
174
175 assert!(cut_vertices.is_empty());
176 assert_eq!(cut_edges.len(), 1);
177 assert!(cut_edges
178 .iter()
179 .find(|(_, _, edge)| edge.get_id() == ab)
180 .is_some());
181 }
182
183 #[test]
184 fn trivial_graph() {
185 let mut graph = MatGraph::init(Mat::<usize>::init());
191 let a = graph.add_vertex();
192 let b = graph.add_vertex();
193 let c = graph.add_vertex();
194 let ab = graph.add_edge_unchecked(a, b, 1.into());
195 let ac = graph.add_edge_unchecked(a, c, 1.into());
196
197 let (cut_vertices, cut_edges) = VertexEdgeCut::init(&graph).execute(&graph);
198
199 assert_eq!(cut_vertices.len(), 1);
200 assert!(cut_vertices.contains(&a));
201 assert_eq!(cut_edges.len(), 2);
202 assert!(vec![ab, ac].into_iter().all(|edge_id| cut_edges
203 .iter()
204 .find(|(_, _, edge)| edge.get_id() == edge_id)
205 .is_some()))
206 }
207
208 #[test]
209 fn trivial_graph_2() {
210 let mut graph = MatGraph::init(Mat::<usize>::init());
217 let a = graph.add_vertex();
218 let b = graph.add_vertex();
219 let c = graph.add_vertex();
220 let d = graph.add_vertex();
221 let ab = graph.add_edge_unchecked(a, b, 1.into());
222 let bc = graph.add_edge_unchecked(a, d, 1.into());
223 let ad = graph.add_edge_unchecked(b, c, 1.into());
224
225 let (cut_vertices, cut_edges) = VertexEdgeCut::init(&graph).execute(&graph);
226
227 assert_eq!(cut_vertices.len(), 2);
228 assert!(vec![a, b]
229 .iter()
230 .all(|vertex_id| cut_vertices.contains(vertex_id)));
231 assert_eq!(cut_edges.len(), 3);
232 assert!(vec![ab, bc, ad].into_iter().all(|edge_id| cut_edges
233 .iter()
234 .find(|(_, _, edge)| edge.get_id() == edge_id)
235 .is_some()))
236 }
237
238 #[test]
239 fn complex_graph() {
240 let mut graph = MatGraph::init(Mat::<usize>::init());
250 let a = graph.add_vertex();
251 let b = graph.add_vertex();
252 let c = graph.add_vertex();
253 let d = graph.add_vertex();
254 let e = graph.add_vertex();
255 let f = graph.add_vertex();
256 let g = graph.add_vertex();
257 let h = graph.add_vertex();
258 let i = graph.add_vertex();
259 let j = graph.add_vertex();
260 let k = graph.add_vertex();
261 let l = graph.add_vertex();
262 let m = graph.add_vertex();
263 let n = graph.add_vertex();
264 graph.add_edge_unchecked(a, b, 1.into());
265 graph.add_edge_unchecked(a, c, 1.into());
266
267 graph.add_edge_unchecked(b, d, 1.into());
268
269 graph.add_edge_unchecked(c, d, 1.into());
270
271 let de = graph.add_edge_unchecked(d, e, 1.into());
272
273 let ef = graph.add_edge_unchecked(e, f, 1.into());
274
275 let fh = graph.add_edge_unchecked(f, h, 1.into());
276
277 graph.add_edge_unchecked(h, i, 1.into());
278 let hg = graph.add_edge_unchecked(h, g, 1.into());
279 graph.add_edge_unchecked(h, m, 1.into());
280
281 graph.add_edge_unchecked(i, j, 1.into());
282
283 graph.add_edge_unchecked(j, k, 1.into());
284
285 graph.add_edge_unchecked(k, l, 1.into());
286
287 graph.add_edge_unchecked(l, m, 1.into());
288
289 let mn = graph.add_edge_unchecked(m, n, 1.into());
290
291 let (cut_vertices, cut_edges) = VertexEdgeCut::init(&graph).execute(&graph);
292
293 assert_eq!(cut_vertices.len(), 5);
294 assert!(vec![d, e, f, h, m]
295 .iter()
296 .all(|vertex_id| cut_vertices.contains(vertex_id)));
297 assert_eq!(cut_edges.len(), 5);
298 assert!(vec![de, ef, fh, hg, mn].into_iter().all(|edge_id| cut_edges
299 .iter()
300 .find(|(_, _, edge)| edge.get_id() == edge_id)
301 .is_some()))
302 }
303
304 #[test]
305 fn non_bridge_edge_between_two_cut_vertices() {
306 let mut graph = MatGraph::init(Mat::<usize>::init());
312 let a = graph.add_vertex();
313 let b = graph.add_vertex();
314 let c = graph.add_vertex();
315 let d = graph.add_vertex();
316 let e = graph.add_vertex();
317 let ab = graph.add_edge_unchecked(a, b, 1.into());
318 graph.add_edge_unchecked(b, c, 1.into());
319 graph.add_edge_unchecked(c, d, 1.into());
320 graph.add_edge_unchecked(b, d, 1.into());
321 let de = graph.add_edge_unchecked(d, e, 1.into());
322
323 let (cut_vertices, cut_edges) = VertexEdgeCut::init(&graph).execute(&graph);
324
325 assert_eq!(cut_vertices.len(), 2);
326 assert!(vec![b, d]
327 .iter()
328 .all(|vertex_id| cut_vertices.contains(vertex_id)));
329 assert_eq!(cut_edges.len(), 2);
330 assert!(vec![ab, de].into_iter().all(|edge_id| cut_edges
331 .iter()
332 .find(|(_, _, edge)| edge.get_id() == edge_id)
333 .is_some()))
334 }
335}