Find the strongly-connected for the given graph.
(graph: G)
| 71 | { |
| 72 | /// Find the strongly-connected for the given graph. |
| 73 | pub fn new<G>(graph: G) -> Self |
| 74 | where |
| 75 | G: Graph<Node>, |
| 76 | { |
| 77 | let nodes = graph.nodes(); |
| 78 | |
| 79 | // The resulting components and their nodes. |
| 80 | let mut component_nodes = vec![]; |
| 81 | let mut components = PrimaryMap::<Scc, Range<u32>>::new(); |
| 82 | |
| 83 | // The DFS index counter. |
| 84 | let mut index = NonMaxU32::default(); |
| 85 | |
| 86 | // The DFS index and the earliest on-stack node reachable from each |
| 87 | // node. |
| 88 | let (min, max) = nodes.size_hint(); |
| 89 | let capacity = max.unwrap_or_else(|| 2 * min); |
| 90 | let mut indices = SecondaryMap::<Node, Option<NonMaxU32>>::with_capacity(capacity); |
| 91 | let mut lowlinks = SecondaryMap::<Node, Option<NonMaxU32>>::with_capacity(capacity); |
| 92 | |
| 93 | // The stack of nodes we are currently finding an SCC for. Not the same |
| 94 | // as the DFS stack: we only pop from this stack once we find the root |
| 95 | // of an SCC. |
| 96 | let mut stack = vec![]; |
| 97 | let mut on_stack = EntitySet::<Node>::new(); |
| 98 | |
| 99 | let mut dfs = Dfs::new(nodes); |
| 100 | while let Some(event) = dfs.next( |
| 101 | &graph, |
| 102 | // We have seen the node before if we have assigned it a DFS index. |
| 103 | |node| indices[node].is_some(), |
| 104 | ) { |
| 105 | match event { |
| 106 | DfsEvent::Pre(node) => { |
| 107 | debug_assert!(indices[node].is_none()); |
| 108 | debug_assert!(lowlinks[node].is_none()); |
| 109 | |
| 110 | // Assign an index to this node. |
| 111 | indices[node] = Some(index); |
| 112 | |
| 113 | // Its current lowlink is itself. This will get updated to |
| 114 | // be accurate as we visit the node's successors. |
| 115 | lowlinks[node] = Some(index); |
| 116 | |
| 117 | // Increment the DFS counter. |
| 118 | index = NonMaxU32::new(index.get() + 1).unwrap(); |
| 119 | |
| 120 | // Push the node onto the SCC stack. |
| 121 | stack.push(node); |
| 122 | let is_newly_on_stack = on_stack.insert(node); |
| 123 | debug_assert!(is_newly_on_stack); |
| 124 | } |
| 125 | |
| 126 | DfsEvent::AfterEdge(node, succ) => { |
| 127 | debug_assert!(indices[node].is_some()); |
| 128 | debug_assert!(lowlinks[node].is_some()); |
| 129 | debug_assert!(lowlinks[node] <= indices[node]); |
| 130 | debug_assert!(indices[succ].is_some()); |
nothing calls this directly
no test coverage detected