use pathfinding::directed::strongly_connected_components::*;
use std::{collections::hash_map::HashMap, sync::LazyLock};
#[expect(clippy::trivially_copy_pass_by_ref)]
fn successors(n: &usize) -> Vec<usize> {
match *n {
0 => vec![2],
1 => vec![0, 5],
2 => vec![1, 4],
3 => vec![2, 9],
4 => vec![3, 5, 10],
5 => vec![6, 8, 13],
6 => vec![7],
7 => vec![8, 15],
8 => vec![6, 15],
9 => vec![10],
10 => vec![11, 12],
11 => vec![9],
12 => vec![11, 13],
13 => vec![14, 15],
14 => vec![13],
15 => vec![],
_ => panic!("error"),
}
}
const EXPECTED: &[&[usize]] = &[
&[0, 1, 2, 3, 4],
&[5],
&[6, 7, 8],
&[9, 10, 11, 12],
&[13, 14],
&[15],
];
static SCC: LazyLock<HashMap<usize, Vec<usize>>> = LazyLock::new(|| {
EXPECTED
.iter()
.flat_map(|v| v.iter().map(move |n| (*n, v.to_vec())))
.collect()
});
#[test]
fn empty_scc() {
let c = strongly_connected_components(&[], successors);
assert_eq!(c.len(), 0);
}
#[test]
fn single_scc() {
let c = strongly_connected_components(&[42], |_| vec![]);
assert_eq!(c, vec![vec![42]]);
let s = strongly_connected_component(&42, |_| vec![]);
assert_eq!(s, vec![42]);
}
#[test]
fn all_scc() {
let mut c = strongly_connected_components(&(0..15).collect::<Vec<_>>(), successors)
.into_iter()
.map(|mut v| {
v.sort_unstable();
v
})
.collect::<Vec<_>>();
c.sort();
assert_eq!(c, *EXPECTED);
}
#[test]
fn some_scc() {
fn starting_from(start: usize) -> Vec<usize> {
let mut c = strongly_connected_components_from(&start, successors)
.into_iter()
.map(|mut v| {
v.sort_unstable();
v
})
.collect::<Vec<_>>();
c.sort();
for v in &c {
assert!(EXPECTED.contains(&&v[..]));
}
c.into_iter().map(|v| v[0]).collect()
}
for &i in &[0, 1, 2, 3, 4] {
assert_eq!(starting_from(i), vec![0, 5, 6, 9, 13, 15]);
}
assert_eq!(starting_from(5), vec![5, 6, 13, 15]);
for &i in &[6, 7, 8] {
assert_eq!(starting_from(i), vec![6, 15]);
}
for &i in &[9, 10, 11, 12] {
assert_eq!(starting_from(i), vec![9, 13, 15]);
}
for &i in &[13, 14] {
assert_eq!(starting_from(i), vec![13, 15]);
}
assert_eq!(starting_from(15), vec![15]);
}
#[test]
fn individual_scc() {
for n in 0..=15 {
let mut c = strongly_connected_component(&n, successors);
c.sort_unstable();
assert_eq!(c, SCC[&n]);
}
}
#[test]
fn loops() {
let mut c = strongly_connected_components(&[0], |_| vec![42]);
c.sort();
assert_eq!(c, vec![vec![0], vec![42]]);
}