use num::traits::NumAssign;
use {EdgeMap, Graph, IndexDigraph, IndexGraph, IndexNodeVec};
pub fn directed<'a, G, Ws, W>(
g: &'a G,
weights: Ws,
src: G::Node,
) -> (IndexNodeVec<'a, G, Option<G::Edge>>, Option<G::Node>)
where
G: 'a + IndexDigraph<'a>,
Ws: EdgeMap<'a, G, W>,
W: NumAssign + Ord + Copy,
{
let mut pred = idxnodevec![g; None];
let mut dist = idxnodevec![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, G, Ws, W>(
g: &'a G,
weights: Ws,
src: G::Node,
) -> (IndexNodeVec<'a, G, Option<G::Edge>>, Option<G::Node>)
where
G: 'a + IndexGraph<'a> + Graph<'a>,
Ws: EdgeMap<'a, G, W>,
W: NumAssign + Ord + Copy,
{
let mut pred = idxnodevec![g; None];
let mut dist = idxnodevec![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)] {
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)
}