Skip to content

Commit e3b286d

Browse files
Compress tree (#83)
* saving progress * saving progress * Update mono_st.rs * saving progress * saving progress * saving progress * another assert * remove * add test * asdf * finish * better * fix * uncomment * Update mono_st.rs * Update mono_range.rs * Update mono_st.rs * fix * change style * nit * change * nits * different style * golf * consistency with c++ PTC * finish doc for mono st * simplify test * add * add docs for mono range * fix typo * nit * fix * nit to docs * now ACs * virt tree * finish docs * finished test * make dist const * consistent var names --------- Co-authored-by: Luke Videckis <lukevideckis@gmail.com> Co-authored-by: Cameron Custer <73217097+cameroncuster@users.noreply.github.com>
1 parent d3a29c7 commit e3b286d

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ path = "examples/data_structures/range_container_handmade.rs"
212212
name = "mono_st"
213213
path = "examples/monotonic/mono_st.rs"
214214

215+
[[example]]
216+
name = "hld_aux_tree"
217+
path = "examples/graphs/hld_aux_tree.rs"
218+
215219
[[example]]
216220
name = "count_rects"
217221
path = "examples/monotonic/count_rects.rs"

examples/graphs/hld_aux_tree.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/problems/GRL_5_B
2+
3+
use proconio::input;
4+
use programming_team_code_rust::graphs::hld::HLD;
5+
use std::collections::VecDeque;
6+
7+
fn main() {
8+
input! {
9+
n: usize,
10+
edges: [(usize, usize, u32); n - 1],
11+
}
12+
13+
let mut adj_weighted = vec![vec![]; n];
14+
let mut adj = vec![vec![]; n];
15+
for &(u, v, w) in &edges {
16+
adj[u].push(v);
17+
adj[v].push(u);
18+
adj_weighted[u].push((v, w));
19+
adj_weighted[v].push((u, w));
20+
}
21+
let adj_weighted = adj_weighted;
22+
23+
let mut dist = vec![0; n];
24+
{
25+
fn dfs(u: usize, p: Option<usize>, adj_weighted: &[Vec<(usize, u32)>], dist: &mut [u32]) {
26+
for &(v, w) in &adj_weighted[u] {
27+
if Some(v) == p {
28+
continue;
29+
}
30+
dist[v] = w + dist[u];
31+
dfs(v, Some(u), adj_weighted, dist);
32+
}
33+
}
34+
dfs(0, None, &adj_weighted, &mut dist);
35+
}
36+
let dist = dist;
37+
38+
let hld = HLD::new(&mut adj, true);
39+
40+
let weighted_dist = |u: usize, v: usize| -> u32 {
41+
let lc = hld.lca(u, v);
42+
dist[u] + dist[v] - 2 * dist[lc]
43+
};
44+
45+
let mut diam_u = 0;
46+
for i in 1..n {
47+
if weighted_dist(0, i) > weighted_dist(0, diam_u) {
48+
diam_u = i;
49+
}
50+
}
51+
let mut diam_v = 0;
52+
for i in 1..n {
53+
if weighted_dist(diam_u, i) > weighted_dist(diam_u, diam_v) {
54+
diam_v = i;
55+
}
56+
}
57+
58+
for u in 0..n {
59+
let (par, to_node) = hld.aux_tree(vec![diam_u, diam_v, u]);
60+
let mut aux_adj = vec![vec![]; par.len()];
61+
for i in 1..par.len() {
62+
let edge_w = dist[to_node[i]] - dist[to_node[par[i]]];
63+
aux_adj[i].push((par[i], edge_w));
64+
aux_adj[par[i]].push((i, edge_w));
65+
}
66+
let mut q = VecDeque::new();
67+
q.push_back((to_node.iter().position(|&x| x == u).unwrap(), None, 0));
68+
let mut res = 0;
69+
while let Some((node, parent, curr_dist)) = q.pop_front() {
70+
res = res.max(curr_dist);
71+
for &(v, w) in &aux_adj[node] {
72+
if Some(v) == parent {
73+
continue;
74+
}
75+
q.push_back((v, Some(node), curr_dist + w));
76+
}
77+
}
78+
println!("{}", res);
79+
}
80+
}

src/graphs/hld.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! # Heavy Light Decomposition
22
33
use crate::graphs::dfs_order::{get_dfs_postorder, get_dfs_preorder};
4+
use crate::monotonic::mono_st::mono_st;
45
use std::ops::Range;
56

67
/// # Example
@@ -201,4 +202,42 @@ impl HLD {
201202
None
202203
}
203204
}
205+
206+
/// # Auxiliary Tree
207+
///
208+
/// - see <https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/CompressTree.h>
209+
///
210+
/// # Example
211+
/// ```
212+
/// use programming_team_code_rust::graphs::hld::HLD;
213+
///
214+
/// let n = 5;
215+
/// let mut adj = vec![vec![]; n];
216+
/// for (u, v) in [(0,1), (1,2), (2,3), (2,4)] {
217+
/// adj[u].push(v);
218+
/// adj[v].push(u);
219+
/// }
220+
///
221+
/// let hld = HLD::new(&mut adj, false);
222+
///
223+
/// let (par, to_node) = hld.aux_tree(vec![0, 3, 4]);
224+
/// // 0, 1, .., par.len()-1 is a topological/dfs order of aux tree
225+
/// assert_eq!(par, [usize::MAX, 0, 1, 1]);
226+
/// assert_eq!(to_node, [0, 2, 3, 4]);
227+
/// ```
228+
///
229+
/// # Complexity
230+
/// - k = nodes.len()
231+
/// - Time: O((k log k) + (k log n))
232+
/// - Space: O(k)
233+
pub fn aux_tree(&self, mut nodes: Vec<usize>) -> (Vec<usize>, Vec<usize>) {
234+
nodes.sort_by(|&u, &v| self.tin[u].cmp(&self.tin[v]));
235+
let siz = nodes.len();
236+
for i in 1..siz {
237+
nodes.push(self.lca(nodes[i - 1], nodes[i]));
238+
}
239+
nodes.sort_by(|&u, &v| self.tin[u].cmp(&self.tin[v]));
240+
nodes.dedup();
241+
(mono_st(&nodes, |&u, &v| self.in_sub(u, v)), nodes)
242+
}
204243
}

0 commit comments

Comments
 (0)