最短路径-Bellman Ford

  1. use std::collections::BTreeMap;
  2. use std::ops::Add;
  3. use std::ops::Neg;
  4. type Graph<V, E> = BTreeMap<V, BTreeMap<V, E>>;
  5. // performs the Bellman-Ford algorithm on the given graph from the given start
  6. // the graph is an undirected graph
  7. //
  8. // if there is a negative weighted loop it returns None
  9. // else it returns a map that for each reachable vertex associates the distance and the predecessor
  10. // since the start has no predecessor but is reachable, map[start] will be None
  11. pub fn bellman_ford<
  12. V: Ord + Copy,
  13. E: Ord + Copy + Add<Output = E> + Neg<Output = E> + std::ops::Sub<Output = E>,
  14. >(
  15. graph: &Graph<V, E>,
  16. start: &V,
  17. ) -> Option<BTreeMap<V, Option<(V, E)>>> {
  18. let mut ans: BTreeMap<V, Option<(V, E)>> = BTreeMap::new();
  19. ans.insert(*start, None);
  20. for _ in 1..(graph.len()) {
  21. for (u, edges) in graph {
  22. let dist_u = match ans.get(u) {
  23. Some(Some((_, d))) => Some(*d),
  24. Some(None) => None,
  25. None => continue,
  26. };
  27. for (v, d) in edges {
  28. match ans.get(v) {
  29. Some(Some((_, dist)))
  30. // if this is a longer path, do nothing
  31. if match dist_u {
  32. Some(dist_u) => dist_u + *d >= *dist,
  33. None => d >= dist,
  34. } => {}
  35. Some(None) => {
  36. match dist_u {
  37. // if dist_u + d < 0 there is a negative loop going by start
  38. // else it's just a longer path
  39. Some(dist_u) if dist_u >= -*d => {}
  40. // negative self edge or negative loop
  41. _ => {
  42. if *d > *d + *d {
  43. return None;
  44. }
  45. }
  46. };
  47. }
  48. // it's a shorter path: either dist_v was infinite or it was longer than dist_u + d
  49. _ => {
  50. ans.insert(
  51. *v,
  52. Some((
  53. *u,
  54. match dist_u {
  55. Some(dist) => dist + *d,
  56. None => *d,
  57. },
  58. )),
  59. );
  60. }
  61. }
  62. }
  63. }
  64. }
  65. for (u, edges) in graph {
  66. for (v, d) in edges {
  67. match (ans.get(u), ans.get(v)) {
  68. (Some(None), Some(None)) if *d > *d + *d => return None,
  69. (Some(None), Some(Some((_, dv)))) if d < dv => return None,
  70. (Some(Some((_, du))), Some(None)) if *du < -*d => return None,
  71. (Some(Some((_, du))), Some(Some((_, dv)))) if *du + *d < *dv => return None,
  72. (_, _) => {}
  73. }
  74. }
  75. }
  76. Some(ans)
  77. }
  78. #[cfg(test)]
  79. mod tests {
  80. use super::{bellman_ford, Graph};
  81. use std::collections::BTreeMap;
  82. fn add_edge<V: Ord + Copy, E: Ord>(graph: &mut Graph<V, E>, v1: V, v2: V, c: E) {
  83. graph.entry(v1).or_insert_with(BTreeMap::new).insert(v2, c);
  84. graph.entry(v2).or_insert_with(BTreeMap::new);
  85. }
  86. #[test]
  87. fn single_vertex() {
  88. let mut graph: Graph<isize, isize> = BTreeMap::new();
  89. graph.insert(0, BTreeMap::new());
  90. let mut dists = BTreeMap::new();
  91. dists.insert(0, None);
  92. assert_eq!(bellman_ford(&graph, &0), Some(dists));
  93. }
  94. #[test]
  95. fn single_edge() {
  96. let mut graph = BTreeMap::new();
  97. add_edge(&mut graph, 0, 1, 2);
  98. let mut dists_0 = BTreeMap::new();
  99. dists_0.insert(0, None);
  100. dists_0.insert(1, Some((0, 2)));
  101. assert_eq!(bellman_ford(&graph, &0), Some(dists_0));
  102. let mut dists_1 = BTreeMap::new();
  103. dists_1.insert(1, None);
  104. assert_eq!(bellman_ford(&graph, &1), Some(dists_1));
  105. }
  106. #[test]
  107. fn tree_1() {
  108. let mut graph = BTreeMap::new();
  109. let mut dists = BTreeMap::new();
  110. dists.insert(1, None);
  111. for i in 1..100 {
  112. add_edge(&mut graph, i, i * 2, i * 2);
  113. add_edge(&mut graph, i, i * 2 + 1, i * 2 + 1);
  114. match dists[&i] {
  115. Some((_, d)) => {
  116. dists.insert(i * 2, Some((i, d + i * 2)));
  117. dists.insert(i * 2 + 1, Some((i, d + i * 2 + 1)));
  118. }
  119. None => {
  120. dists.insert(i * 2, Some((i, i * 2)));
  121. dists.insert(i * 2 + 1, Some((i, i * 2 + 1)));
  122. }
  123. }
  124. }
  125. assert_eq!(bellman_ford(&graph, &1), Some(dists));
  126. }
  127. #[test]
  128. fn graph_1() {
  129. let mut graph = BTreeMap::new();
  130. add_edge(&mut graph, 'a', 'c', 12);
  131. add_edge(&mut graph, 'a', 'd', 60);
  132. add_edge(&mut graph, 'b', 'a', 10);
  133. add_edge(&mut graph, 'c', 'b', 20);
  134. add_edge(&mut graph, 'c', 'd', 32);
  135. add_edge(&mut graph, 'e', 'a', 7);
  136. let mut dists_a = BTreeMap::new();
  137. dists_a.insert('a', None);
  138. dists_a.insert('c', Some(('a', 12)));
  139. dists_a.insert('d', Some(('c', 44)));
  140. dists_a.insert('b', Some(('c', 32)));
  141. assert_eq!(bellman_ford(&graph, &'a'), Some(dists_a));
  142. let mut dists_b = BTreeMap::new();
  143. dists_b.insert('b', None);
  144. dists_b.insert('a', Some(('b', 10)));
  145. dists_b.insert('c', Some(('a', 22)));
  146. dists_b.insert('d', Some(('c', 54)));
  147. assert_eq!(bellman_ford(&graph, &'b'), Some(dists_b));
  148. let mut dists_c = BTreeMap::new();
  149. dists_c.insert('c', None);
  150. dists_c.insert('b', Some(('c', 20)));
  151. dists_c.insert('d', Some(('c', 32)));
  152. dists_c.insert('a', Some(('b', 30)));
  153. assert_eq!(bellman_ford(&graph, &'c'), Some(dists_c));
  154. let mut dists_d = BTreeMap::new();
  155. dists_d.insert('d', None);
  156. assert_eq!(bellman_ford(&graph, &'d'), Some(dists_d));
  157. let mut dists_e = BTreeMap::new();
  158. dists_e.insert('e', None);
  159. dists_e.insert('a', Some(('e', 7)));
  160. dists_e.insert('c', Some(('a', 19)));
  161. dists_e.insert('d', Some(('c', 51)));
  162. dists_e.insert('b', Some(('c', 39)));
  163. assert_eq!(bellman_ford(&graph, &'e'), Some(dists_e));
  164. }
  165. #[test]
  166. fn graph_2() {
  167. let mut graph = BTreeMap::new();
  168. add_edge(&mut graph, 0, 1, 6);
  169. add_edge(&mut graph, 0, 3, 7);
  170. add_edge(&mut graph, 1, 2, 5);
  171. add_edge(&mut graph, 1, 3, 8);
  172. add_edge(&mut graph, 1, 4, -4);
  173. add_edge(&mut graph, 2, 1, -2);
  174. add_edge(&mut graph, 3, 2, -3);
  175. add_edge(&mut graph, 3, 4, 9);
  176. add_edge(&mut graph, 4, 0, 3);
  177. add_edge(&mut graph, 4, 2, 7);
  178. let mut dists_0 = BTreeMap::new();
  179. dists_0.insert(0, None);
  180. dists_0.insert(1, Some((2, 2)));
  181. dists_0.insert(2, Some((3, 4)));
  182. dists_0.insert(3, Some((0, 7)));
  183. dists_0.insert(4, Some((1, -2)));
  184. assert_eq!(bellman_ford(&graph, &0), Some(dists_0));
  185. let mut dists_1 = BTreeMap::new();
  186. dists_1.insert(0, Some((4, -1)));
  187. dists_1.insert(1, None);
  188. dists_1.insert(2, Some((4, 3)));
  189. dists_1.insert(3, Some((0, 6)));
  190. dists_1.insert(4, Some((1, -4)));
  191. assert_eq!(bellman_ford(&graph, &1), Some(dists_1));
  192. let mut dists_2 = BTreeMap::new();
  193. dists_2.insert(0, Some((4, -3)));
  194. dists_2.insert(1, Some((2, -2)));
  195. dists_2.insert(2, None);
  196. dists_2.insert(3, Some((0, 4)));
  197. dists_2.insert(4, Some((1, -6)));
  198. assert_eq!(bellman_ford(&graph, &2), Some(dists_2));
  199. let mut dists_3 = BTreeMap::new();
  200. dists_3.insert(0, Some((4, -6)));
  201. dists_3.insert(1, Some((2, -5)));
  202. dists_3.insert(2, Some((3, -3)));
  203. dists_3.insert(3, None);
  204. dists_3.insert(4, Some((1, -9)));
  205. assert_eq!(bellman_ford(&graph, &3), Some(dists_3));
  206. let mut dists_4 = BTreeMap::new();
  207. dists_4.insert(0, Some((4, 3)));
  208. dists_4.insert(1, Some((2, 5)));
  209. dists_4.insert(2, Some((4, 7)));
  210. dists_4.insert(3, Some((0, 10)));
  211. dists_4.insert(4, None);
  212. assert_eq!(bellman_ford(&graph, &4), Some(dists_4));
  213. }
  214. #[test]
  215. fn graph_with_negative_loop() {
  216. let mut graph = BTreeMap::new();
  217. add_edge(&mut graph, 0, 1, 6);
  218. add_edge(&mut graph, 0, 3, 7);
  219. add_edge(&mut graph, 1, 2, 5);
  220. add_edge(&mut graph, 1, 3, 8);
  221. add_edge(&mut graph, 1, 4, -4);
  222. add_edge(&mut graph, 2, 1, -4);
  223. add_edge(&mut graph, 3, 2, -3);
  224. add_edge(&mut graph, 3, 4, 9);
  225. add_edge(&mut graph, 4, 0, 3);
  226. add_edge(&mut graph, 4, 2, 7);
  227. assert_eq!(bellman_ford(&graph, &0), None);
  228. assert_eq!(bellman_ford(&graph, &1), None);
  229. assert_eq!(bellman_ford(&graph, &2), None);
  230. assert_eq!(bellman_ford(&graph, &3), None);
  231. assert_eq!(bellman_ford(&graph, &4), None);
  232. }
  233. }