use std::{
collections::{HashMap, HashSet},
hash::Hash,
};
mod tarjan;
pub trait Scc {
type Vertex: Copy + Eq + Hash;
fn vertices(&self) -> impl '_ + IntoIterator<Item = Self::Vertex>;
fn successors(&self, v: Self::Vertex) -> impl '_ + IntoIterator<Item = Self::Vertex>;
fn strongly_connected_components(&self) -> Components<Self::Vertex> {
tarjan::scc(self)
}
}
pub struct Components<V> {
list: Vec<Vec<V>>,
vertex_to_component: HashMap<V, usize>,
successors: Vec<HashSet<usize>>,
}
impl<V> Components<V> {
pub fn len(&self) -> usize {
self.list.len()
}
pub fn is_empty(&self) -> bool {
self.list.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &[V]> {
self.list.iter().map(Vec::as_slice)
}
pub fn vertex_component_index(&self, v: &V) -> Option<usize>
where
V: Eq + Hash,
{
self.vertex_to_component.get(v).cloned()
}
pub fn get_by_index(&self, i: usize) -> Option<&[V]> {
self.list.get(i).map(Vec::as_slice)
}
pub fn get(&self, v: &V) -> Option<&[V]>
where
V: Eq + Hash
{
self.get_by_index(self.vertex_component_index(v)?)
}
pub fn successors(&self, i: usize) -> Option<impl '_ + Iterator<Item = usize>> {
self.successors.get(i).map(|s| s.iter().cloned())
}
pub fn is_cyclic(&self, i: usize) -> bool {
self.successors.get(i).unwrap().contains(&i)
}
fn remove_indirect_successors(&self, result: &mut HashSet<usize>, i: usize) {
for j in self.successors(i).unwrap() {
result.remove(&j);
self.remove_indirect_successors(result, j);
}
}
pub fn direct_successors(&self, i: usize) -> Option<HashSet<usize>> {
let mut result: HashSet<_> = self.successors(i)?.collect();
for j in self.successors(i).unwrap() {
self.remove_indirect_successors(&mut result, j);
}
Some(result)
}
pub fn depths(&self) -> Vec<usize> {
let mut depth = vec![0; self.list.len()];
let mut stack: Vec<_> = depth.iter().cloned().enumerate().collect();
while let Some((i, new_depth)) = stack.pop() {
if depth[i] == 0 || new_depth > depth[i] {
depth[i] = new_depth;
for c in self.successors(i).unwrap() {
if c != i {
stack.push((c, new_depth + 1))
}
}
}
}
depth
}
pub fn predecessors(&self) -> Vec<HashSet<usize>> {
let mut predecessors = Vec::new();
predecessors.resize_with(self.list.len(), HashSet::default);
for (i, successors) in self.successors.iter().enumerate() {
for &j in successors {
predecessors[j].insert(i);
}
}
predecessors
}
pub fn order_by_depth(&self) -> Vec<usize> {
let depth = self.depths();
let mut ordered_components: Vec<_> = (0..self.list.len()).collect();
ordered_components.sort_unstable_by_key(|i| depth[*i]);
ordered_components
}
}
pub fn depths(predecessors: &[HashSet<usize>]) -> Vec<usize> {
let mut depth = vec![0; predecessors.len()];
let mut stack: Vec<_> = depth.iter().cloned().enumerate().collect();
while let Some((i, new_depth)) = stack.pop() {
if depth[i] == 0 || new_depth > depth[i] {
depth[i] = new_depth;
for &c in &predecessors[i] {
if c != i {
stack.push((c, new_depth + 1))
}
}
}
}
depth
}