haar_lib/graph/
bellman_ford.rs1use crate::graph::*;
4pub use crate::num::num_inf::NumInf;
5use crate::num::one_zero::Zero;
6use std::{cmp::min, ops::Add};
7
8pub fn bellman_ford<D: Direction, E: EdgeTrait>(
10 g: &Graph<D, E>,
11 src: usize,
12) -> Vec<NumInf<E::Weight>>
13where
14 E::Weight: Copy + Ord + Zero + Add<Output = E::Weight>,
15{
16 use self::NumInf::*;
17
18 let n = g.len();
19 let mut ret = vec![Inf; n];
20
21 ret[src] = Value(E::Weight::zero());
22
23 for i in 0..n {
24 for s in 0..n {
25 for e in g.nodes[s].edges.iter() {
26 let (to, cost) = (e.to(), e.weight());
27 if let Value(x) = ret[s] {
28 match ret[to] {
29 Value(y) => {
30 if x + cost < y && i == n - 1 {
31 ret[to] = NegInf;
32 } else {
33 ret[to] = Value(min(y, x + cost));
34 }
35 }
36 Inf => {
37 ret[to] = Value(x + cost);
38 }
39 _ => {}
40 }
41 }
42 }
43 }
44 }
45
46 for _ in 0..n {
47 for s in 0..n {
48 for e in g.nodes[s].edges.iter() {
49 if ret[s].is_neg_inf() {
50 ret[e.to()] = NegInf;
51 }
52 }
53 }
54 }
55
56 ret
57}
58
59#[cfg(test)]
60mod tests {
61 use super::{NumInf::*, *};
62
63 #[test]
64 fn test() {
65 let mut g = Graph::<Directed, _>::new(4);
66 g.extend(
67 vec![(0, 1, 2), (0, 2, 3), (1, 2, -5), (1, 3, 1), (2, 3, 2)]
68 .into_iter()
69 .map(|(u, v, w)| Edge::new(u, v, w, ())),
70 );
71 assert_eq!(
72 bellman_ford(&g, 0),
73 [Value(0), Value(2), Value(-3), Value(-1)]
74 );
75
76 let mut g = Graph::<Directed, _>::new(4);
77 g.extend(
78 vec![(0, 1, 2), (0, 2, 3), (1, 2, -5), (1, 3, 1), (2, 3, 2)]
79 .into_iter()
80 .map(|(u, v, w)| Edge::new(u, v, w, ())),
81 );
82 assert_eq!(bellman_ford(&g, 1), [Inf, Value(0), Value(-5), Value(-3)]);
83 }
84}