use num::traits::{NumAssign};
use {Graph, IndexGraph, IndexDigraph, NodeVec, EdgeSlice};
pub fn directed<'a, 'b, G, W>(g: &'a G, weights: &EdgeSlice<'a,'b,G,W>, src: G::Node)
-> (NodeVec<'a,G,Option<G::Edge>>, Option<G::Node>)
where G: 'a + IndexDigraph<'a>,
W: NumAssign + Ord + Copy,
{
let mut pred = nodevec![g; None];
let mut dist = nodevec![g; W::zero()];
dist[src] = W::zero();
for i in 0..g.num_nodes() {
let mut changed = false;
for e in g.edges() {
let (u, v) = (g.src(e), g.snk(e));
if u != src && pred[u].is_none() {
continue
}
let newdist = dist[u] + weights[e];
if dist[v] > newdist || pred[v].is_none() {
dist[v] = newdist;
pred[v] = Some(e);
changed = true;
if i + 1 == g.num_nodes() {
return (pred, Some(v));
}
}
}
if !changed {
break;
}
}
(pred, None)
}
pub fn undirected<'a, 'b, G, W>(g: &'a G, weights: &EdgeSlice<'a,'b,G,W>, src: G::Node)
-> (NodeVec<'a,G,Option<G::Edge>>, Option<G::Node>)
where G: 'a + IndexGraph<'a> + Graph<'a>,
W: NumAssign + Ord + Copy,
{
let mut pred = nodevec![g; None];
let mut dist = nodevec![g; W::zero()];
dist[src] = W::zero();
for i in 0..g.num_nodes() {
let mut changed = false;
for e in g.edges() {
let (u, v) = g.enodes(e);
for &(u, v) in [(u, v), (v, u)].iter() {
if u != src && pred[u].is_none() {
continue
}
let newdist = dist[u] + weights[e];
if dist[v] > newdist || pred[v].is_none() {
dist[v] = newdist;
pred[v] = Some(e);
changed = true;
if i + 1 == g.num_nodes() {
return (pred, Some(v));
}
}
}
}
if !changed {
break;
}
}
(pred, None)
}