use crate::dag_sampling::index_set::IndexSet;
use std::collections::VecDeque;
#[derive(Clone, Debug)]
pub struct Graph {
pub(crate) n: usize,
pub(crate) m: usize,
neighbors: Vec<IndexSet>,
}
impl Graph {
pub fn from_adjacency_list(adjacency_list: Vec<Vec<usize>>) -> Graph {
let n = adjacency_list.len();
let m = adjacency_list.iter().map(Vec::len).sum::<usize>() / 2;
let neighbors = adjacency_list.into_iter().map(IndexSet::from).collect();
Graph { n, m, neighbors }
}
pub fn from_edge_list(edge_list: Vec<(usize, usize)>, n: usize) -> Graph {
let mut adjacency_list = vec![Vec::new(); n];
for &(u, v) in &edge_list {
adjacency_list[u].push(v);
adjacency_list[v].push(u);
}
Graph::from_adjacency_list(adjacency_list)
}
pub(crate) fn neighbors(&self, u: usize) -> std::slice::Iter<'_, usize> {
self.neighbors[u].iter()
}
pub(crate) fn bfs_ordering(&self) -> Vec<usize> {
let mut queue = VecDeque::new();
let mut visited = vec![false; self.n];
let mut visit_ordering = Vec::new();
queue.push_back(0);
visited[0] = true;
while let Some(u) = queue.pop_front() {
visit_ordering.push(u);
for &v in self.neighbors(u) {
if !visited[v] {
queue.push_back(v);
visited[v] = true;
}
}
}
visit_ordering
}
pub(crate) fn connected_components(&self) -> Vec<Graph> {
let mut queue = VecDeque::new();
let mut component_of = vec![usize::MAX; self.n];
let mut new_id = vec![usize::MAX; self.n];
let mut cnt = 0;
let mut component_vertices: Vec<Vec<usize>> = Vec::new();
for i in 0..self.n {
if component_of[i] == usize::MAX {
let mut component = Vec::new();
queue.push_back(i);
component_of[i] = cnt;
new_id[i] = component.len();
component.push(i);
while let Some(u) = queue.pop_front() {
for &v in self.neighbors(u) {
if component_of[v] == usize::MAX {
queue.push_back(v);
component_of[v] = cnt;
new_id[v] = component.len();
component.push(v);
}
}
}
component_vertices.push(component);
cnt += 1;
}
}
let mut adjacency_lists: Vec<Vec<Vec<usize>>> = component_vertices
.iter()
.map(|component| vec![Vec::new(); component.len()])
.collect();
for i in 0..self.n {
for &j in self.neighbors(i) {
adjacency_lists[component_of[i]][new_id[i]].push(new_id[j]);
}
}
adjacency_lists
.into_iter()
.map(Graph::from_adjacency_list)
.collect()
}
}