competitive/graph/
low_link.rs1use super::UndirectedSparseGraph;
2
3pub struct LowLink<'a> {
4 graph: &'a UndirectedSparseGraph,
5 pub low: Vec<usize>,
6 pub ord: Vec<usize>,
7 pub articulation: Vec<usize>,
8 pub bridge: Vec<(usize, usize)>,
9}
10impl<'a> LowLink<'a> {
11 pub fn new(graph: &'a UndirectedSparseGraph) -> Self {
12 let mut self_ = Self {
13 graph,
14 low: vec![0; graph.vertices_size()],
15 ord: vec![usize::MAX; graph.vertices_size()],
16 articulation: vec![],
17 bridge: vec![],
18 };
19 for u in graph.vertices() {
20 if self_.ord[u] == usize::MAX {
21 self_.dfs(u, graph.vertices_size(), &mut 0);
22 }
23 }
24 self_
25 }
26 fn dfs(&mut self, u: usize, p: usize, now_ord: &mut usize) {
27 self.low[u] = *now_ord;
28 self.ord[u] = *now_ord;
29 *now_ord += 1;
30 let mut is_articulation = false;
31 let mut cnt = 0;
32 for a in self.graph.adjacencies(u) {
33 if self.ord[a.to] == usize::MAX {
34 cnt += 1;
35 self.dfs(a.to, u, now_ord);
36 self.low[u] = self.low[u].min(self.low[a.to]);
37 is_articulation |= p < self.graph.vertices_size() && self.ord[u] <= self.low[a.to];
38 if self.ord[u] < self.low[a.to] {
39 self.bridge.push((u.min(a.to), u.max(a.to)));
40 }
41 } else if a.to != p {
42 self.low[u] = self.low[u].min(self.ord[a.to]);
43 }
44 }
45 is_articulation |= p == self.graph.vertices_size() && cnt > 1;
46 if is_articulation {
47 self.articulation.push(u);
48 }
49 }
50}