Skip to content

Commit c2fe241

Browse files
lca with precomp dfs order (#34)
1 parent a085719 commit c2fe241

File tree

4 files changed

+37
-37
lines changed

4 files changed

+37
-37
lines changed

examples/graphs/lca_yosupo.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,35 @@ fn main() {
99
q: usize,
1010
}
1111

12-
// forest with an undirected tree and a rooted directed tree
13-
let mut undir_for = vec![vec![]; n + n];
12+
// undirected tree and a rooted directed tree
13+
let mut undir = vec![vec![]; n + n];
1414
let mut dir = vec![vec![]; n];
1515
for c in 1..n {
1616
input! {
1717
p: usize,
1818
}
1919

2020
// undirected tree
21-
for &(u, v) in [(p, c), (p + n, c + n)].iter() {
22-
undir_for[u].push(v);
23-
undir_for[v].push(u);
24-
}
21+
undir[p].push(c);
22+
undir[c].push(p);
2523

2624
// directed tree
2725
dir[p].push(c);
2826
}
2927

30-
let undir_lca = LCA::new(&undir_for);
28+
let undir_lca = LCA::new(&undir);
3129
let dir_lca = LCA::new(&dir);
3230
for _ in 0..q {
3331
input! {
3432
u: usize,
3533
v: usize,
3634
}
37-
let res_undir1 = undir_lca.lca(u, v);
38-
let res_undir2 = undir_lca.lca(u + n, v + n) - n;
35+
36+
let res_undir = undir_lca.lca(u, v);
3937
let res_dir = dir_lca.lca(u, v);
40-
assert_eq!(res_undir1, res_undir2);
41-
assert_eq!(res_undir1, res_dir);
42-
println!("{}", res_dir);
38+
39+
assert_eq!(res_undir, res_dir);
40+
41+
println!("{}", res_undir);
4342
}
4443
}

src/graphs/dfs_order.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
pub fn dfs_order(adj: &[Vec<usize>]) -> Vec<usize> {
2+
let n = adj.len();
3+
let mut order = Vec::with_capacity(n);
4+
fn dfs(u: usize, p: usize, adj: &[Vec<usize>], order: &mut Vec<usize>) {
5+
order.push(u);
6+
for &v in &adj[u] {
7+
if v != p {
8+
dfs(v, u, adj, order);
9+
}
10+
}
11+
}
12+
dfs(0, 0, adj, &mut order);
13+
order
14+
}

src/graphs/lca.rs

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! # Lowest Common Ancestor
22
33
use crate::data_structures::rmq::RMQ;
4+
use crate::graphs::dfs_order::dfs_order;
45

56
/// # Example
67
/// ```
@@ -23,48 +24,33 @@ use crate::data_structures::rmq::RMQ;
2324
/// ```
2425
pub struct LCA {
2526
tin: Vec<usize>,
26-
p: Vec<Option<usize>>,
27+
p: Vec<usize>,
2728
rmq: RMQ<(usize, usize)>,
2829
}
2930

3031
impl LCA {
3132
/// Create a new LCA struct
3233
///
33-
/// `adj` can be undirected tree, directed tree (rooted at node 0), or a forest of undirected
34-
/// trees
34+
/// `adj` can be undirected tree or a directed tree (rooted at node 0)
3535
///
3636
/// # Complexity (n = adj.len())
3737
/// - Time: O(n log n)
3838
/// - Space: O(n log n)
3939
pub fn new(adj: &[Vec<usize>]) -> Self {
4040
let n = adj.len();
41-
let mut d = vec![0; n];
4241
let mut tin = vec![0; n];
43-
let mut p = vec![None; n];
44-
let mut order = Vec::with_capacity(n);
45-
fn dfs(
46-
u: usize,
47-
p: &mut [Option<usize>],
48-
adj: &[Vec<usize>],
49-
d: &mut [usize],
50-
tin: &mut [usize],
51-
order: &mut Vec<usize>,
52-
) {
53-
tin[u] = order.len();
54-
order.push(u);
42+
let mut p = vec![0; n];
43+
let mut d = vec![0; n];
44+
let order = dfs_order(adj);
45+
for (i, &u) in order.iter().enumerate() {
46+
tin[u] = i;
5547
for &v in &adj[u] {
56-
if p[u] != Some(v) {
48+
if v != p[u] {
49+
p[v] = u;
5750
d[v] = d[u] + 1;
58-
p[v] = Some(u);
59-
dfs(v, p, adj, d, tin, order);
6051
}
6152
}
6253
}
63-
for s in 0..n {
64-
if p[s].is_none() {
65-
dfs(s, &mut p, adj, &mut d, &mut tin, &mut order);
66-
}
67-
}
6854
let d_with_order: Vec<(usize, usize)> = order.iter().map(|&u| (d[u], u)).collect();
6955
let rmq = RMQ::new(&d_with_order, std::cmp::min);
7056
LCA { tin, p, rmq }
@@ -83,6 +69,6 @@ impl LCA {
8369
if le > ri {
8470
std::mem::swap(&mut le, &mut ri);
8571
}
86-
self.p[self.rmq.query(le + 1..ri + 1).1].unwrap()
72+
self.p[self.rmq.query(le + 1..ri + 1).1]
8773
}
8874
}

src/graphs/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
//! # Graph Algorithms
2+
mod dfs_order;
23
pub mod dijk;
34
pub mod lca;

0 commit comments

Comments
 (0)