procon_lib_rs

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub CoCo-Japan-pan/procon_lib_rs

:warning: crates/tree/auxiliary_tree/src/lib.rs

Depends on

Required by

Code

//! LCAベースの圧縮木  
//! [Auxiliary Tree](https://atcoder.jp/contests/abc340/editorial/9249)
use euler_tour::EulerTour;

#[derive(Debug)]
pub struct AuxiliaryTree {
    pub euler_tour: EulerTour,
}

impl AuxiliaryTree {
    pub fn new(graph: &[Vec<usize>], root: usize) -> Self {
        let euler_tour = EulerTour::new(graph, root);
        Self { euler_tour }
    }

    /// LCAの関係を保ったまま圧縮された木を返す  
    /// 空配列を渡すと`(vec![], vec![], None)`を返す  
    /// 空でなければ`(頂点集合, (親,子)のペアの集合, Some(根))`を返す  
    /// 頂点集合はその番号のままソートしている  
    /// `O(KlogK) (K = vertex_subset.len())`  
    /// 圧縮された木のサイズは高々`2K-1`  
    pub fn gen_auxiliary_tree(
        &self,
        mut vertex_subset: Vec<usize>,
    ) -> (Vec<usize>, Vec<(usize, usize)>, Option<usize>) {
        if vertex_subset.is_empty() {
            return (vec![], vec![], None);
        }
        // pre-order順にソート(オイラーツアーのfirst_occurrenceで代用)
        vertex_subset.sort_by_key(|&v| self.euler_tour.first_occurrence[v]);
        {
            // LCAを追加
            let mut append = Vec::with_capacity(vertex_subset.len() - 1);
            for ad in vertex_subset.windows(2) {
                append.push(self.euler_tour.lca(ad[0], ad[1]));
            }
            vertex_subset.append(&mut append);
        }
        // LCAを追加したものをpre-order順にソート
        vertex_subset.sort_by_key(|&v| self.euler_tour.first_occurrence[v]);
        // 重複削除
        vertex_subset.dedup();

        // 構築
        let mut par_v_pairs = Vec::with_capacity(vertex_subset.len() - 1);
        let mut stack = Vec::with_capacity(vertex_subset.len());
        stack.push(vertex_subset[0]);
        for &v in vertex_subset.iter().skip(1) {
            while let Some(&top) = stack.last() {
                if self.euler_tour.last_occurrence[top] < self.euler_tour.first_occurrence[v] {
                    stack.pop();
                } else {
                    break;
                }
            }
            if let Some(&top) = stack.last() {
                par_v_pairs.push((top, v));
            }
            stack.push(v);
        }
        let root = stack[0];
        // 将来圧縮グラフの構築時に二分探索することを見越して、番号そのままでソートしておく
        vertex_subset.sort_unstable();
        (vertex_subset, par_v_pairs, Some(root))
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    /// example from https://smijake3.hatenablog.com/entry/2019/09/15/200200
    fn test_auxiliary_tree() {
        /*  0
           / \
          1   2
             / \
            3   9
            |   | \
            4   10 12
           /|\   \
          5 6 7   11
              \
               8
        => (1, 5, 8, 11)で圧縮
            0
           / \
          1   2
             / \
            4   11
           / \
          5   8
        */
        let parent = vec![usize::MAX, 0, 0, 2, 3, 4, 4, 4, 6, 2, 9, 10, 9];
        let graph = {
            let mut graph = vec![vec![]; parent.len()];
            for (i, &p) in parent.iter().enumerate().skip(1) {
                graph[p].push(i);
                graph[i].push(p);
            }
            graph
        };
        let auxiliary_tree = AuxiliaryTree::new(&graph, 0);
        let (_, par_ver_pair, root) = auxiliary_tree.gen_auxiliary_tree(vec![1, 5, 8, 11]);
        assert_eq!(root, Some(0));
        assert_eq!(
            par_ver_pair,
            vec![(0, 1), (0, 2), (2, 4), (4, 5), (4, 8), (2, 11)]
        );
    }
}
Traceback (most recent call last):
  File "/opt/hostedtoolcache/Python/3.13.9/x64/lib/python3.13/site-packages/onlinejudge_verify/documentation/build.py", line 71, in _render_source_code_stat
    bundled_code = language.bundle(stat.path, basedir=basedir, options={'include_paths': [basedir]}).decode()
                   ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.13.9/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/rust.py", line 288, in bundle
    raise NotImplementedError
NotImplementedError
Back to top page