use crate::core::{Graph, IgraphResult};
pub fn is_net_free(graph: &Graph) -> IgraphResult<bool> {
let n = graph.vcount();
if n < 6 {
return Ok(true);
}
let n_usize = n as usize;
let mut adj = vec![vec![false; n_usize]; n_usize];
for v in 0..n {
let nbrs = graph.neighbors(v)?;
for &w in &nbrs {
adj[v as usize][w as usize] = true;
adj[w as usize][v as usize] = true;
}
}
let verts: Vec<usize> = (0..n_usize).collect();
for (i0, &a) in verts.iter().enumerate() {
for (i1, &b) in verts.iter().enumerate().skip(i0 + 1) {
if !adj[a][b] {
continue;
}
for &c in &verts[(i1 + 1)..] {
if !adj[a][c] || !adj[b][c] {
continue;
}
if has_net_pendants(&adj, a, b, c, n_usize) {
return Ok(false);
}
}
}
}
Ok(true)
}
fn has_net_pendants(adj: &[Vec<bool>], a: usize, b: usize, c: usize, n: usize) -> bool {
let tri = [a, b, c];
let pend_a: Vec<usize> = (0..n)
.filter(|&v| !tri.contains(&v) && adj[v][a] && !adj[v][b] && !adj[v][c])
.collect();
let pend_b: Vec<usize> = (0..n)
.filter(|&v| !tri.contains(&v) && !adj[v][a] && adj[v][b] && !adj[v][c])
.collect();
let pend_c: Vec<usize> = (0..n)
.filter(|&v| !tri.contains(&v) && !adj[v][a] && !adj[v][b] && adj[v][c])
.collect();
for &da in &pend_a {
for &db in &pend_b {
if adj[da][db] {
continue;
}
for &dc in &pend_c {
if dc != da && dc != db && !adj[dc][da] && !adj[dc][db] {
return true;
}
}
}
}
false
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_graph() {
let g = Graph::with_vertices(0);
assert!(is_net_free(&g).unwrap());
}
#[test]
fn single_vertex() {
let g = Graph::with_vertices(1);
assert!(is_net_free(&g).unwrap());
}
#[test]
fn triangle() {
let mut g = Graph::with_vertices(3);
g.add_edge(0, 1).unwrap();
g.add_edge(1, 2).unwrap();
g.add_edge(2, 0).unwrap();
assert!(is_net_free(&g).unwrap());
}
#[test]
fn net_graph() {
let mut g = Graph::with_vertices(6);
g.add_edge(0, 1).unwrap();
g.add_edge(1, 2).unwrap();
g.add_edge(2, 0).unwrap();
g.add_edge(0, 3).unwrap();
g.add_edge(1, 4).unwrap();
g.add_edge(2, 5).unwrap();
assert!(!is_net_free(&g).unwrap());
}
#[test]
fn k4() {
let mut g = Graph::with_vertices(4);
for i in 0..4u32 {
for j in (i + 1)..4 {
g.add_edge(i, j).unwrap();
}
}
assert!(is_net_free(&g).unwrap());
}
#[test]
fn k5() {
let mut g = Graph::with_vertices(5);
for i in 0..5u32 {
for j in (i + 1)..5 {
g.add_edge(i, j).unwrap();
}
}
assert!(is_net_free(&g).unwrap());
}
#[test]
fn c5() {
let mut g = Graph::with_vertices(5);
g.add_edge(0, 1).unwrap();
g.add_edge(1, 2).unwrap();
g.add_edge(2, 3).unwrap();
g.add_edge(3, 4).unwrap();
g.add_edge(4, 0).unwrap();
assert!(is_net_free(&g).unwrap());
}
#[test]
fn star() {
let mut g = Graph::with_vertices(5);
g.add_edge(0, 1).unwrap();
g.add_edge(0, 2).unwrap();
g.add_edge(0, 3).unwrap();
g.add_edge(0, 4).unwrap();
assert!(is_net_free(&g).unwrap());
}
#[test]
fn path_p6() {
let mut g = Graph::with_vertices(6);
g.add_edge(0, 1).unwrap();
g.add_edge(1, 2).unwrap();
g.add_edge(2, 3).unwrap();
g.add_edge(3, 4).unwrap();
g.add_edge(4, 5).unwrap();
assert!(is_net_free(&g).unwrap());
}
#[test]
fn triangle_with_one_pendant() {
let mut g = Graph::with_vertices(4);
g.add_edge(0, 1).unwrap();
g.add_edge(1, 2).unwrap();
g.add_edge(2, 0).unwrap();
g.add_edge(0, 3).unwrap();
assert!(is_net_free(&g).unwrap());
}
#[test]
fn triangle_with_two_pendants() {
let mut g = Graph::with_vertices(5);
g.add_edge(0, 1).unwrap();
g.add_edge(1, 2).unwrap();
g.add_edge(2, 0).unwrap();
g.add_edge(0, 3).unwrap();
g.add_edge(1, 4).unwrap();
assert!(is_net_free(&g).unwrap());
}
#[test]
fn net_with_extra_edges() {
let mut g = Graph::with_vertices(6);
g.add_edge(0, 1).unwrap();
g.add_edge(1, 2).unwrap();
g.add_edge(2, 0).unwrap();
g.add_edge(0, 3).unwrap();
g.add_edge(1, 4).unwrap();
g.add_edge(2, 5).unwrap();
g.add_edge(3, 4).unwrap();
assert!(is_net_free(&g).unwrap());
}
#[test]
fn edgeless() {
let g = Graph::with_vertices(6);
assert!(is_net_free(&g).unwrap());
}
#[test]
fn directed_treated_as_undirected() {
let mut g = Graph::new(6, true).unwrap();
g.add_edge(0, 1).unwrap();
g.add_edge(1, 2).unwrap();
g.add_edge(2, 0).unwrap();
g.add_edge(0, 3).unwrap();
g.add_edge(1, 4).unwrap();
g.add_edge(2, 5).unwrap();
assert!(!is_net_free(&g).unwrap());
}
}