pub(super) struct OrigGraph {
pub(super) n: u32,
pub(super) tail: Vec<u32>,
pub(super) head: Vec<u32>,
pub(super) back_arc: Vec<u32>,
out_arc_offsets: Vec<u32>,
}
impl OrigGraph {
pub(super) fn build(n: u32, edges: &[(u32, u32)]) -> Option<Self> {
let mut arcs: Vec<(u32, u32)> = Vec::with_capacity(edges.len() * 2);
for &(u, v) in edges {
debug_assert!(u < n && v < n && u != v);
arcs.push((u, v));
arcs.push((v, u));
}
if arcs.is_empty() {
return None;
}
arcs.sort_unstable();
arcs.dedup();
let arc_count = arcs.len();
let mut tail = Vec::with_capacity(arc_count);
let mut head = Vec::with_capacity(arc_count);
for (u, v) in arcs {
tail.push(u);
head.push(v);
}
let mut out_arc_offsets = vec![0u32; (n + 1) as usize];
for &t in &tail {
out_arc_offsets[(t + 1) as usize] += 1;
}
for v in 1..=n as usize {
out_arc_offsets[v] += out_arc_offsets[v - 1];
}
let mut back_arc = vec![0u32; arc_count];
for i in 0..arc_count {
let u = tail[i];
let v = head[i];
let lo = out_arc_offsets[v as usize] as usize;
let hi = out_arc_offsets[(v + 1) as usize] as usize;
let slice = &head[lo..hi];
let pos = slice.binary_search(&u).expect("symmetric graph");
back_arc[i] = (lo + pos) as u32;
}
Some(OrigGraph {
n,
tail,
head,
back_arc,
out_arc_offsets,
})
}
#[inline]
pub(super) fn out_arcs(&self, v: u32) -> std::ops::Range<u32> {
self.out_arc_offsets[v as usize]..self.out_arc_offsets[v as usize + 1]
}
}
pub(super) fn is_connected(g: &OrigGraph) -> bool {
if g.n == 0 {
return false;
}
let mut seen = vec![false; g.n as usize];
let mut stack = vec![0u32];
seen[0] = true;
let mut count = 1u32;
while let Some(v) = stack.pop() {
for a in g.out_arcs(v) {
let h = g.head[a as usize];
if !seen[h as usize] {
seen[h as usize] = true;
count += 1;
stack.push(h);
}
}
}
count == g.n
}