use crate::llp;
use epserde::prelude::*;
use rayon::{
iter::{IntoParallelRefMutIterator, ParallelIterator},
slice::ParallelSliceMut,
};
mod tarjan;
pub use tarjan::*;
mod kosaraju;
pub use kosaraju::*;
mod symm_seq;
pub use symm_seq::*;
mod symm_par;
pub use symm_par::*;
#[derive(Epserde, Clone, Copy, Debug)]
pub struct Sccs<C: AsRef<[usize]> = Box<[usize]>> {
num_components: usize,
components: C,
}
impl<C: AsRef<[usize]>> Sccs<C> {
pub fn new(num_components: usize, components: C) -> Self {
Sccs {
num_components,
components,
}
}
#[inline(always)]
pub fn num_components(&self) -> usize {
self.num_components
}
#[inline(always)]
pub fn components(&self) -> &[usize] {
self.components.as_ref()
}
pub fn compute_sizes(&self) -> Box<[usize]> {
let mut sizes = vec![0; self.num_components()];
for &node_component in self.components() {
sizes[node_component] += 1;
}
sizes.into_boxed_slice()
}
}
impl<C: AsMut<[usize]> + AsRef<[usize]>> Sccs<C> {
pub fn sort_by_size(&mut self) -> Box<[usize]> {
let mut sizes = self.compute_sizes();
assert!(sizes.len() == self.num_components());
let mut sort_perm = Vec::from_iter(0..sizes.len());
sort_perm.sort_unstable_by(|&x, &y| sizes[y].cmp(&sizes[x]));
let mut inv_perm = vec![0; sizes.len()];
sort_perm
.iter()
.enumerate()
.for_each(|(i, &x)| inv_perm[x] = i);
self.components
.as_mut()
.iter_mut()
.for_each(|node_component| *node_component = inv_perm[*node_component]);
sizes.sort_by(|&x, &y| y.cmp(&x));
sizes
}
pub fn par_sort_by_size(&mut self) -> Box<[usize]> {
let mut sizes = self.compute_sizes();
assert!(sizes.len() == self.num_components());
let mut sort_perm = Vec::from_iter(0..sizes.len());
sort_perm.par_sort_unstable_by(|&x, &y| sizes[y].cmp(&sizes[x]));
let mut inv_perm = vec![0; sizes.len()];
llp::invert_permutation(&sort_perm, &mut inv_perm);
self.components
.as_mut()
.par_iter_mut()
.for_each(|node_component| *node_component = inv_perm[*node_component]);
sizes.par_sort_by(|&x, &y| y.cmp(&x));
sizes
}
}