Skip to content

Commit 93deb9b

Browse files
authored
another idea to clean up dfs (#73)
* another idea to clean up dfs * different style * convert bridges to new style * hld example refactor * Revert "hld example refactor" This reverts commit e5a77a1. --------- Co-authored-by: Luke Videckis <lukevideckis@gmail.com>
1 parent a59b50f commit 93deb9b

File tree

2 files changed

+72
-95
lines changed

2 files changed

+72
-95
lines changed

src/graphs/bridges.rs

Lines changed: 34 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -24,69 +24,53 @@
2424
/// - Time: O(V + E)
2525
/// - Space: O(V)
2626
pub fn get_bridges(adj: &[Vec<(usize, usize)>], m: usize) -> (usize, Vec<bool>, Vec<usize>) {
27-
#[allow(clippy::too_many_arguments)]
28-
fn dfs(
29-
u: usize,
30-
p_id: Option<usize>,
31-
adj: &[Vec<(usize, usize)>],
32-
timer: &mut usize,
33-
tin: &mut [usize],
34-
num_2_edge_ccs: &mut usize,
35-
is_bridge: &mut [bool],
36-
two_edge_ccid: &mut [usize],
37-
st: &mut Vec<usize>,
38-
) -> usize {
39-
tin[u] = *timer;
40-
let (mut low, st_sz) = (*timer, st.len());
41-
*timer += 1;
42-
st.push(u);
27+
let n = adj.len();
28+
struct Env {
29+
timer: usize,
30+
tin: Vec<usize>,
31+
num_2_edge_ccs: usize,
32+
is_bridge: Vec<bool>,
33+
two_edge_ccid: Vec<usize>,
34+
st: Vec<usize>,
35+
}
36+
let mut e = Env {
37+
timer: 1,
38+
tin: vec![0; n],
39+
num_2_edge_ccs: 0,
40+
is_bridge: vec![false; m],
41+
two_edge_ccid: vec![0; n],
42+
st: Vec::with_capacity(n),
43+
};
44+
fn dfs(e: &mut Env, u: usize, p_id: Option<usize>, adj: &[Vec<(usize, usize)>]) -> usize {
45+
e.tin[u] = e.timer;
46+
let (mut low, st_sz) = (e.timer, e.st.len());
47+
e.timer += 1;
48+
e.st.push(u);
4349
for &(v, e_id) in &adj[u] {
4450
if Some(e_id) == p_id {
4551
continue;
4652
}
47-
if tin[v] == 0 {
48-
low = low.min(dfs(
49-
v,
50-
Some(e_id),
51-
adj,
52-
timer,
53-
tin,
54-
num_2_edge_ccs,
55-
is_bridge,
56-
two_edge_ccid,
57-
st,
58-
));
53+
if e.tin[v] == 0 {
54+
low = low.min(dfs(e, v, Some(e_id), adj));
5955
}
60-
low = low.min(tin[v]);
56+
low = low.min(e.tin[v]);
6157
}
62-
if tin[u] == low {
58+
if e.tin[u] == low {
6359
if let Some(p) = p_id {
64-
is_bridge[p] = true;
60+
e.is_bridge[p] = true;
6561
}
66-
for &id in st.iter().skip(st_sz) {
67-
two_edge_ccid[id] = *num_2_edge_ccs;
62+
for &id in e.st.iter().skip(st_sz) {
63+
e.two_edge_ccid[id] = e.num_2_edge_ccs;
6864
}
69-
st.truncate(st_sz);
70-
*num_2_edge_ccs += 1;
65+
e.st.truncate(st_sz);
66+
e.num_2_edge_ccs += 1;
7167
}
7268
low
7369
}
74-
let (n, mut timer, mut num_2_edge_ccs, mut is_bridge) = (adj.len(), 1, 0, vec![false; m]);
75-
let (mut tin, mut two_edge_ccid, mut st) = (vec![0; n], vec![0; n], Vec::with_capacity(n));
7670
for i in 0..n {
77-
if tin[i] == 0 {
78-
dfs(
79-
i,
80-
None,
81-
adj,
82-
&mut timer,
83-
&mut tin,
84-
&mut num_2_edge_ccs,
85-
&mut is_bridge,
86-
&mut two_edge_ccid,
87-
&mut st,
88-
);
71+
if e.tin[i] == 0 {
72+
dfs(&mut e, i, None, adj);
8973
}
9074
}
91-
(num_2_edge_ccs, is_bridge, two_edge_ccid)
75+
(e.num_2_edge_ccs, e.is_bridge, e.two_edge_ccid)
9276
}

src/graphs/cuts.rs

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,67 +32,60 @@
3232
/// - Time: O(V + E)
3333
/// - Space: O(V)
3434
pub fn get_cuts(adj: &[Vec<(usize, usize)>], m: usize) -> (usize, Vec<bool>, Vec<usize>) {
35-
#[allow(clippy::too_many_arguments)]
36-
fn dfs(
37-
u: usize,
38-
p_id: Option<usize>,
39-
adj: &[Vec<(usize, usize)>],
40-
timer: &mut usize,
41-
tin: &mut [usize],
42-
num_bccs: &mut usize,
43-
is_cut: &mut [bool],
44-
bcc_id: &mut [usize],
45-
st: &mut Vec<usize>,
46-
) -> usize {
47-
tin[u] = *timer;
48-
let (mut low, mut deg) = (*timer, 0);
49-
*timer += 1;
35+
let n = adj.len();
36+
struct Env {
37+
timer: usize,
38+
tin: Vec<usize>,
39+
num_bccs: usize,
40+
is_cut: Vec<bool>,
41+
bcc_id: Vec<usize>,
42+
st: Vec<usize>,
43+
}
44+
let mut e = Env {
45+
timer: 1,
46+
tin: vec![0; n],
47+
num_bccs: 0,
48+
is_cut: vec![false; n],
49+
bcc_id: vec![0; m],
50+
st: Vec::with_capacity(m),
51+
};
52+
fn dfs(e: &mut Env, u: usize, p_id: Option<usize>, adj: &[Vec<(usize, usize)>]) -> usize {
53+
e.tin[u] = e.timer;
54+
let (mut low, mut deg) = (e.timer, 0);
55+
e.timer += 1;
5056
for &(v, e_id) in &adj[u] {
5157
assert_ne!(u, v);
5258
if Some(e_id) == p_id {
5359
continue;
5460
}
55-
if tin[v] == 0 {
56-
let st_sz = st.len();
57-
st.push(e_id);
58-
let low_ch = dfs(v, Some(e_id), adj, timer, tin, num_bccs, is_cut, bcc_id, st);
59-
if low_ch >= tin[u] {
60-
is_cut[u] = true;
61-
for &id in st.iter().skip(st_sz) {
62-
bcc_id[id] = *num_bccs;
61+
if e.tin[v] == 0 {
62+
let st_sz = e.st.len();
63+
e.st.push(e_id);
64+
let low_ch = dfs(e, v, Some(e_id), adj);
65+
if low_ch >= e.tin[u] {
66+
e.is_cut[u] = true;
67+
for &id in e.st.iter().skip(st_sz) {
68+
e.bcc_id[id] = e.num_bccs;
6369
}
64-
st.truncate(st_sz);
65-
*num_bccs += 1;
70+
e.st.truncate(st_sz);
71+
e.num_bccs += 1;
6672
}
6773
low = low.min(low_ch);
6874
deg += 1;
69-
} else if tin[v] < tin[u] {
70-
st.push(e_id);
71-
low = low.min(tin[v]);
75+
} else if e.tin[v] < e.tin[u] {
76+
e.st.push(e_id);
77+
low = low.min(e.tin[v]);
7278
}
7379
}
7480
if p_id.is_none() {
75-
is_cut[u] = deg > 1;
81+
e.is_cut[u] = deg > 1;
7682
}
7783
low
7884
}
79-
let (n, mut timer, mut num_bccs, mut bcc_id, mut st) =
80-
(adj.len(), 1, 0, vec![0; m], Vec::with_capacity(m));
81-
let (mut tin, mut is_cut) = (vec![0; n], vec![false; n]);
8285
for i in 0..n {
83-
if tin[i] == 0 {
84-
dfs(
85-
i,
86-
None,
87-
adj,
88-
&mut timer,
89-
&mut tin,
90-
&mut num_bccs,
91-
&mut is_cut,
92-
&mut bcc_id,
93-
&mut st,
94-
);
86+
if e.tin[i] == 0 {
87+
dfs(&mut e, i, None, adj);
9588
}
9689
}
97-
(num_bccs, is_cut, bcc_id)
90+
(e.num_bccs, e.is_cut, e.bcc_id)
9891
}

0 commit comments

Comments
 (0)