#![allow(clippy::type_complexity)]
use crate::num::traits::NumAssign;
use crate::traits::{Graph, IndexDigraph, IndexGraph};
pub fn directed<'a, G, W, F>(g: &'a G, weights: F, src: G::Node<'a>) -> (Vec<Option<G::Edge<'a>>>, Option<G::Node<'a>>)
where
G: 'a + IndexDigraph,
W: NumAssign + Ord + Copy,
F: Fn(G::Edge<'a>) -> W,
{
let mut pred = vec![None; g.num_nodes()];
let mut dist = vec![W::zero(); g.num_nodes()];
let src = g.node_id(src);
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));
let uid = g.node_id(u);
let vid = g.node_id(v);
if uid != src && pred[uid].is_none() {
continue;
}
let newdist = dist[uid] + weights(e);
if dist[vid] > newdist || pred[vid].is_none() {
dist[vid] = newdist;
pred[vid] = 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<'a>,
) -> (Vec<Option<G::Edge<'a>>>, Option<G::Node<'a>>)
where
G: IndexGraph + Graph,
W: NumAssign + Ord + Copy,
F: Fn(G::Edge<'a>) -> W,
{
let mut pred = vec![None; g.num_nodes()];
let mut dist = vec![W::zero(); g.num_nodes()];
let src = g.node_id(src);
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)] {
let uid = g.node_id(u);
let vid = g.node_id(v);
if uid != src && pred[uid].is_none() {
continue;
}
let newdist = dist[uid] + weights(e);
if dist[vid] > newdist || pred[vid].is_none() {
dist[vid] = newdist;
pred[vid] = Some(e);
changed = true;
if i + 1 == g.num_nodes() {
return (pred, Some(v));
}
}
}
}
if !changed {
break;
}
}
(pred, None)
}