1pub use crate::graph::lowlink::Lowlink;
4
5type Vertices = Vec<usize>;
6type Edges = Vec<(usize, usize)>;
7
8pub fn biconnected(ll: &Lowlink) -> Vec<(Vertices, Edges)> {
10 let n = ll.size;
11
12 let mut check = vec![false; n];
13 let mut ret = vec![];
14 let mut temp = vec![];
15 let mut vcheck = vec![false; n];
16
17 for i in 0..n {
18 if !check[i] {
19 if ll.ch[i].is_empty() && ll.par[i].is_none() {
20 ret.push((vec![i], vec![]));
21 } else {
22 dfs(i, ll, &mut check, &mut vcheck, &mut temp, &mut ret);
23 }
24 }
25 }
26
27 ret
28}
29
30fn dfs(
31 cur: usize,
32 ll: &Lowlink,
33 check: &mut [bool],
34 vcheck: &mut [bool],
35 stack: &mut Vec<(usize, usize)>,
36 ret: &mut Vec<(Vertices, Edges)>,
37) {
38 check[cur] = true;
39
40 for &to in ll.ch[cur].iter().chain(ll.back[cur].iter()) {
41 if !check[to] || ll.ord[to] < ll.ord[cur] {
42 stack.push((cur, to));
43 }
44 if !check[to] {
45 dfs(to, ll, check, vcheck, stack, ret);
46
47 if ll.low[to] >= ll.ord[cur] {
48 let mut es = vec![];
49 let mut vs = vec![];
50
51 while let Some(e) = stack.pop() {
52 let (u, v) = e;
53 es.push(e);
54
55 if !vcheck[u] {
56 vs.push(u);
57 vcheck[u] = true;
58 }
59 if !vcheck[v] {
60 vs.push(v);
61 vcheck[v] = true;
62 }
63
64 if u == cur && v == to {
65 break;
66 }
67 }
68
69 for &i in &vs {
70 vcheck[i] = false;
71 }
72
73 ret.push((vs, es));
74 }
75 }
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::biconnected;
82 use crate::btreeset;
83 use crate::graph::{lowlink::Lowlink, *};
84 use std::collections::BTreeSet;
85 use std::iter::FromIterator;
86
87 #[test]
88 fn test() {
89 let mut g = Graph::<Undirected, _>::new(4);
90 g.extend(
91 vec![(0, 3), (0, 1), (3, 0), (2, 1), (2, 3)]
92 .into_iter()
93 .map(|(u, v)| Edge::new(u, v, (), ())),
94 );
95
96 assert_eq!(
97 BTreeSet::from_iter(
98 biconnected(&Lowlink::new(&g))
99 .into_iter()
100 .map(|(v, _)| BTreeSet::from_iter(v))
101 ),
102 btreeset! {
103 btreeset!{0, 1, 2, 3}
104 }
105 );
106
107 let mut g = Graph::<Undirected, _>::new(10);
108 g.extend(
109 vec![
110 (0, 6),
111 (0, 8),
112 (1, 2),
113 (1, 6),
114 (2, 6),
115 (3, 6),
116 (3, 9),
117 (4, 9),
118 (4, 7),
119 (5, 6),
120 (5, 9),
121 (6, 8),
122 ]
123 .into_iter()
124 .map(|(u, v)| Edge::new(u, v, (), ())),
125 );
126
127 assert_eq!(
128 BTreeSet::from_iter(
129 biconnected(&Lowlink::new(&g))
130 .into_iter()
131 .map(|(v, _)| BTreeSet::from_iter(v))
132 ),
133 btreeset! {
134 btreeset!{0, 6, 8},
135 btreeset!{1, 2, 6},
136 btreeset!{3, 5, 6, 9},
137 btreeset!{4, 7},
138 btreeset!{4, 9}
139 }
140 );
141
142 let mut g = Graph::<Undirected, _>::new(5);
143 g.extend(
144 vec![(0, 1), (1, 0), (0, 1)]
145 .into_iter()
146 .map(|(u, v)| Edge::new(u, v, (), ())),
147 );
148
149 assert_eq!(
150 BTreeSet::from_iter(
151 biconnected(&Lowlink::new(&g))
152 .into_iter()
153 .map(|(v, _)| BTreeSet::from_iter(v))
154 ),
155 btreeset! {
156 btreeset!{0, 1},
157 btreeset!{2},
158 btreeset!{3},
159 btreeset!{4}
160 }
161 );
162 }
163}