use std::hash::Hash;
use std::collections::HashSet;
use crate::graph::Graph;
use crate::matching::Matching;
use crate::traversal::{ depth_first };
pub fn greedy<'a, N: 'a+Clone+Eq+Hash>(
graph: &'a impl Graph<'a, N>
) -> Matching<N> {
let root = match graph.nodes().next() {
Some(root) => root,
None => return Matching::build(vec![ ]).unwrap()
};
let mut nodes = HashSet::new();
let mut edges = Vec::new();
for step in depth_first(graph, root).unwrap() {
if !nodes.contains(step.source) && !nodes.contains(step.target) {
edges.push((step.source.clone(), step.target.clone()));
nodes.insert(step.source);
nodes.insert(step.target);
}
}
Matching::build(edges).unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::graph::IndexGraph;
macro_rules! set {
( $( $x:expr ), * ) => {
{
#[allow(unused_mut)]
let mut set = HashSet::new();
$(
set.insert($x);
)*
set
}
};
}
#[test]
fn empty() {
let graph = IndexGraph::build(vec![ ]).unwrap();
let matching = greedy(&graph);
assert!(matching.is_empty());
}
#[test]
fn p1() {
let graph = IndexGraph::build(vec![
vec! [ ]
]).unwrap();
let matching = greedy(&graph);
assert!(matching.is_empty());
}
#[test]
fn p2() {
let graph = IndexGraph::build(vec![
vec![ 1 ],
vec![ 0 ]
]).unwrap();
let matching = greedy(&graph);
assert_eq!(matching.edges().collect::<HashSet<_>>(), set![
(&0, &1)
]);
}
#[test]
fn p3() {
let graph = IndexGraph::build(vec![
vec![ 1 ],
vec![ 0, 2 ],
vec![ 1 ]
]).unwrap();
let matching = greedy(&graph);
assert_eq!(matching.edges().collect::<HashSet<_>>(), set![
(&0, &1)
]);
}
#[test]
fn p4() {
let graph = IndexGraph::build(vec![
vec![ 1 ],
vec![ 0, 2 ],
vec![ 1, 3 ],
vec![ 2 ]
]).unwrap();
let matching = greedy(&graph);
assert_eq!(matching.edges().collect::<HashSet<_>>(), set![
(&0, &1),
(&2, &3)
]);
}
#[test]
fn s3() {
let graph = IndexGraph::build(vec![
vec![ 1 ],
vec![ 0, 2, 3 ],
vec![ 1 ],
vec![ 1 ]
]).unwrap();
let matching = greedy(&graph);
assert_eq!(matching.edges().collect::<HashSet<_>>(), set![
(&0, &1)
]);
}
#[test]
fn c6() {
let graph = IndexGraph::build(vec![
vec![ 1, 5 ],
vec![ 0, 2 ],
vec![ 1, 3 ],
vec![ 2, 4 ],
vec![ 3, 5 ],
vec![ 4, 0 ]
]).unwrap();
let matching = greedy(&graph);
assert_eq!(matching.edges().collect::<HashSet<_>>(), set![
(&0, &1),
(&2, &3),
(&4, &5)
]);
}
}