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/graph/lowlink/src/lib.rs

Required by

Code

use std::collections::VecDeque;

struct InternalLowLink<'a> {
    graph: &'a Vec<Vec<usize>>,
    ord: Vec<usize>,
    low: Vec<usize>,
    used: Vec<bool>,
    cur_ord: usize,
    articulation_points: Vec<usize>,
    bridges: Vec<(usize, usize)>,
}

impl<'a> InternalLowLink<'a> {
    fn build(graph: &'a Vec<Vec<usize>>) -> Self {
        let n = graph.len();
        let mut ret = Self {
            graph,
            ord: vec![n; n],
            low: vec![n; n],
            used: vec![false; n],
            cur_ord: 0,
            articulation_points: vec![],
            bridges: vec![],
        };
        for v in 0..n {
            if ret.used[v] {
                continue;
            }
            ret.dfs(v, !0);
        }
        ret
    }

    fn dfs(&mut self, v: usize, p: usize) {
        self.ord[v] = self.cur_ord;
        self.low[v] = self.cur_ord;
        self.cur_ord += 1;
        self.used[v] = true;
        let mut child_cnt = 0;
        let mut is_aps = false;
        // 同じ辺が二つ以上ある場合はそれは後退辺となるので注意する
        let mut checked_parent = false;
        for &to in &self.graph[v] {
            if to == p && !checked_parent {
                checked_parent = true;
                continue;
            }
            if !self.used[to] {
                child_cnt += 1;
                self.dfs(to, v);
                // 子からのlowの伝播
                self.low[v] = self.low[v].min(self.low[to]);
                // vがDFS木の根でない場合、その子toについてord[v] <= low[to]ならばvは関節点
                if p != !0 && self.ord[v] <= self.low[to] {
                    is_aps = true;
                }
                // ord[v] < low[to]ならば(v, to)は橋
                if self.ord[v] < self.low[to] {
                    self.bridges.push((v.min(to), v.max(to)));
                }
            } else {
                // 後退辺
                self.low[v] = self.low[v].min(self.ord[to]);
            }
        }
        // vがDFS木の根である場合、子が2つ以上ならばvは関節点
        if p == !0 && child_cnt >= 2 {
            is_aps = true;
        }
        if is_aps {
            self.articulation_points.push(v);
        }
    }
}

/// 無向グラフに対するLowLink
#[derive(Debug)]
pub struct LowLink<'a> {
    graph: &'a Vec<Vec<usize>>,
    /// pre-order
    pub ord: Vec<usize>,
    pub low: Vec<usize>,
    /// 関節点 ソートはされていない
    pub articulation_points: Vec<usize>,
    /// 橋 ソートはされていない
    pub bridges: Vec<(usize, usize)>,
}

impl<'a> LowLink<'a> {
    /// 隣接リスト形式で無向グラフを受け取り、ord,low,関節点,橋を返す `O(V + E)`  
    pub fn new(graph: &'a Vec<Vec<usize>>) -> Self {
        let internal = InternalLowLink::build(graph);
        Self {
            graph,
            ord: internal.ord,
            low: internal.low,
            articulation_points: internal.articulation_points,
            bridges: internal.bridges,
        }
    }

    #[inline]
    /// 頂点uとvを結ぶ辺が橋かどうかを返す `O(1)`    
    /// ただしuとvが隣接していることを仮定しているので注意
    pub fn is_bridge(&self, u: usize, v: usize) -> bool {
        if self.ord[u] > self.ord[v] {
            self.ord[v] < self.low[u]
        } else {
            self.ord[u] < self.low[v]
        }
    }

    /// 2重辺連結成分分解 `O(V + E)`  
    /// `(各連結成分の二重配列, 各頂点が属する二重辺連結成分のidxの配列)` を返す  
    /// 橋を消し、連結成分をまとめる 頂点を排他的に分解することになる  
    /// 連結成分を縮約して頂点とみなし、橋を辺とみなすことで森(元々連結なら木)になる
    pub fn two_edge_cc(&self) -> (Vec<Vec<usize>>, Vec<usize>) {
        let mut cur_cc_id = 0;
        let mut ccs = vec![];
        let mut cc_id = vec![!0; self.graph.len()];
        for v in 0..self.graph.len() {
            if cc_id[v] != !0 {
                continue;
            }
            let mut component = vec![v];
            cc_id[v] = cur_cc_id;
            let mut que = VecDeque::new();
            que.push_back(v);
            while let Some(v) = que.pop_front() {
                for &to in &self.graph[v] {
                    if cc_id[to] != !0 {
                        continue;
                    }
                    // 橋
                    if self.is_bridge(v, to) {
                        continue;
                    }
                    cc_id[to] = cur_cc_id;
                    component.push(to);
                    que.push_back(to);
                }
            }
            cur_cc_id += 1;
            ccs.push(component);
        }
        (ccs, cc_id)
    }
}
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