/rust/registry/src/index.crates.io-1949cf8c6b5b557f/petgraph-0.8.3/src/algo/bridges.rs
Line | Count | Source |
1 | | use crate::visit::{ |
2 | | EdgeRef, IntoEdgeReferences, IntoNeighbors, IntoNodeIdentifiers, NodeIndexable, |
3 | | }; |
4 | | |
5 | | use alloc::{vec, vec::Vec}; |
6 | | |
7 | | /// Find all [bridges](https://en.wikipedia.org/wiki/Bridge_(graph_theory)) in a simple undirected graph. |
8 | | /// |
9 | | /// # Arguments |
10 | | /// * `graph`: a simple undirected graph. |
11 | | /// |
12 | | /// # Returns |
13 | | /// * `impl Iterator`: the iterator of edge references `G::EdgeRef` representing the edges |
14 | | /// of the input graph that are bridges. The order of the edges is arbitrary. |
15 | | /// |
16 | | /// # Complexity |
17 | | /// * Time complexity: **O(|V| + |E|)**. |
18 | | /// * Auxiliary space: **O(|V|)**. |
19 | | /// |
20 | | /// where **|V|** is the number of nodes and **|E|** is the number of edges. |
21 | | /// |
22 | | /// |
23 | | /// # Examples |
24 | | /// |
25 | | /// ``` |
26 | | /// use petgraph::algo::bridges::bridges; |
27 | | /// use petgraph::graph::UnGraph; |
28 | | /// use petgraph::visit::EdgeRef; |
29 | | /// |
30 | | /// // Create the following graph: |
31 | | /// // 0----1 4 |
32 | | /// // | __/| |
33 | | /// // 5----2/---3 |
34 | | /// |
35 | | /// let mut g = UnGraph::new_undirected(); |
36 | | /// let n0 = g.add_node(()); |
37 | | /// let n1 = g.add_node(()); |
38 | | /// let n2 = g.add_node(()); |
39 | | /// let n3 = g.add_node(()); |
40 | | /// let n4 = g.add_node(()); |
41 | | /// let n5 = g.add_node(()); |
42 | | /// let e0 = g.add_edge(n0, n1, ()); |
43 | | /// let e1 = g.add_edge(n1, n2, ()); |
44 | | /// let e2 = g.add_edge(n2, n3, ()); |
45 | | /// let e3 = g.add_edge(n3, n4, ()); |
46 | | /// let e4 = g.add_edge(n2, n4, ()); |
47 | | /// let e5 = g.add_edge(n5, n2, ()); |
48 | | /// |
49 | | /// let bridges: Vec<_> = bridges(&g).map(|edge_ref| edge_ref.id()).collect(); |
50 | | /// |
51 | | /// // The bridges in this graph are the undirected edges {2, 5}, {1, 2}, {0, 1}. |
52 | | /// assert_eq!(bridges, vec![e0, e1, e5]); |
53 | | /// ``` |
54 | 0 | pub fn bridges<G>(graph: G) -> impl Iterator<Item = G::EdgeRef> |
55 | 0 | where |
56 | 0 | G: IntoNodeIdentifiers + IntoNeighbors + NodeIndexable + IntoEdgeReferences, |
57 | | { |
58 | 0 | let mut clock: usize = 0usize; |
59 | | // If and when a node was visited by the dfs |
60 | 0 | let mut visit_time = vec![None; graph.node_bound()]; |
61 | | // Lowest time on a node that is the target of a back-edge from the subtree rooted |
62 | | // at the indexed node. |
63 | 0 | let mut earliest_backedge = vec![usize::MAX; graph.node_bound()]; |
64 | | |
65 | 0 | for start in 0..graph.node_bound() { |
66 | | // If node hasn't been visited yet, make it the root of a new dfs-tree in the forest. |
67 | 0 | if visit_time[start].is_none() { |
68 | 0 | visit_time[start] = Some(clock); |
69 | 0 | clock += 1; |
70 | | |
71 | | // Perform a DFS starting at start |
72 | 0 | let start = graph.from_index(start); |
73 | 0 | let mut stack: Vec<(G::NodeId, G::Neighbors)> = vec![(start, graph.neighbors(start))]; |
74 | | |
75 | 0 | while let Some((stack_frame, rest_of_stack)) = stack.split_last_mut() { |
76 | 0 | let &mut (node, ref mut neighbors) = stack_frame; |
77 | 0 | let parent = rest_of_stack.last().map(|&(n, _)| n); |
78 | | |
79 | 0 | let node_index = graph.to_index(node); |
80 | | |
81 | 0 | if let Some(child) = neighbors.next() { |
82 | | // Pre-order DFS |
83 | 0 | if parent != Some(child) { |
84 | 0 | let child_index = graph.to_index(child); |
85 | | |
86 | 0 | if let Some(time) = visit_time[child_index] { |
87 | 0 | earliest_backedge[node_index] = earliest_backedge[node_index].min(time); |
88 | 0 | } else { |
89 | 0 | visit_time[child_index] = Some(clock); |
90 | 0 | clock += 1; |
91 | 0 | stack.push((child, graph.neighbors(child))); |
92 | 0 | } |
93 | 0 | } |
94 | | } else { |
95 | | // Post-order DFS |
96 | 0 | if let Some(parent) = parent { |
97 | 0 | let parent_index = graph.to_index(parent); |
98 | 0 | earliest_backedge[parent_index] = |
99 | 0 | earliest_backedge[parent_index].min(earliest_backedge[node_index]); |
100 | 0 | } |
101 | 0 | stack.pop(); |
102 | | } |
103 | | } |
104 | 0 | } |
105 | | } |
106 | | |
107 | 0 | graph.edge_references().filter(move |edge| { |
108 | 0 | let source_index = graph.to_index(edge.source()); |
109 | 0 | let target_index = graph.to_index(edge.target()); |
110 | | |
111 | | // All nodes have been visited by the time we return, so unwraps are safe. |
112 | | // The node with the lower visit time is the "parent" in the dfs-forest created above. |
113 | 0 | let (parent, node) = |
114 | 0 | if visit_time[source_index].unwrap() < visit_time[target_index].unwrap() { |
115 | 0 | (source_index, target_index) |
116 | | } else { |
117 | 0 | (target_index, source_index) |
118 | | }; |
119 | | |
120 | | // If there's no back-edge to before parent, then this the only way from parent to here |
121 | | // is directly from parent, so it's a bridge edge. |
122 | 0 | earliest_backedge[node] > visit_time[parent].unwrap() |
123 | 0 | }) |
124 | 0 | } |
125 | | |
126 | | #[cfg(test)] |
127 | | mod tests { |
128 | | use super::*; |
129 | | use crate::graph::EdgeReference; |
130 | | use crate::graph::UnGraph; |
131 | | use crate::visit::EdgeRef; |
132 | | |
133 | | #[test] |
134 | | fn test_bridges() { |
135 | | let mut g = UnGraph::<i8, i8>::new_undirected(); |
136 | | let bridge_nodes = |g: &_| { |
137 | | bridges(g) |
138 | | .map(|e: EdgeReference<_>| (e.source(), e.target())) |
139 | | .collect::<Vec<_>>() |
140 | | }; |
141 | | |
142 | | assert_eq!(bridge_nodes(&g), vec![]); |
143 | | let n0 = g.add_node(0); |
144 | | assert_eq!(bridge_nodes(&g), vec![]); |
145 | | let n1 = g.add_node(1); |
146 | | assert_eq!(bridge_nodes(&g), vec![]); |
147 | | g.add_edge(n0, n1, 0); |
148 | | assert_eq!(bridge_nodes(&g), vec![(n0, n1)]); |
149 | | let n2 = g.add_node(2); |
150 | | assert_eq!(bridge_nodes(&g), vec![(n0, n1)]); |
151 | | g.add_edge(n2, n1, 1); |
152 | | assert_eq!(bridge_nodes(&g), vec![(n0, n1), (n2, n1)]); |
153 | | g.add_edge(n0, n2, 2); |
154 | | assert_eq!(bridge_nodes(&g), vec![]); |
155 | | let n3 = g.add_node(3); |
156 | | let n4 = g.add_node(4); |
157 | | g.add_edge(n2, n3, 3); |
158 | | g.add_edge(n3, n4, 4); |
159 | | assert_eq!(bridge_nodes(&g), vec![(n2, n3), (n3, n4)]); |
160 | | g.add_edge(n3, n0, 5); |
161 | | assert_eq!(bridge_nodes(&g), vec![(n3, n4)]); |
162 | | } |
163 | | } |