#![allow(clippy::type_complexity)]
use crate::num::traits::NumAssign;
use crate::traits::{Graph, IndexDigraph, IndexGraph};
use crate::vec::NodeVec;
pub fn directed<'a, G, W, F>(g: &'a G, weights: F, src: G::Node) -> (NodeVec<&'a G, Option<G::Edge>>, Option<G::Node>)
where
G: 'a + IndexDigraph<'a>,
W: NumAssign + Ord + Copy,
F: Fn(G::Edge) -> W,
{
let mut pred = NodeVec::new(g, None);
let mut dist = NodeVec::new(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, W, F>(g: &'a G, weights: F, src: G::Node) -> (NodeVec<&'a G, Option<G::Edge>>, Option<G::Node>)
where
G: 'a + IndexGraph<'a> + Graph<'a>,
W: NumAssign + Ord + Copy,
F: Fn(G::Edge) -> W,
{
let mut pred = NodeVec::new(g, None);
let mut dist = NodeVec::new(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)
}