Prim算法(最小生成树)

  1. use std::cmp::Reverse;
  2. use std::collections::{BTreeMap, BinaryHeap};
  3. use std::ops::Add;
  4. type Graph<V, E> = BTreeMap<V, BTreeMap<V, E>>;
  5. fn add_edge<V: Ord + Copy, E: Ord + Add + Copy>(graph: &mut Graph<V, E>, v1: V, v2: V, c: E) {
  6. graph.entry(v1).or_insert_with(BTreeMap::new).insert(v2, c);
  7. graph.entry(v2).or_insert_with(BTreeMap::new).insert(v1, c);
  8. }
  9. // selects a start and run the algorithm from it
  10. pub fn prim<V: Ord + Copy + std::fmt::Debug, E: Ord + Add + Copy + std::fmt::Debug>(
  11. graph: &Graph<V, E>,
  12. ) -> Graph<V, E> {
  13. match graph.keys().next() {
  14. Some(v) => prim_with_start(graph, *v),
  15. None => BTreeMap::new(),
  16. }
  17. }
  18. // only works for a connected graph
  19. // if the given graph is not connected it will return the MST of the connected subgraph
  20. pub fn prim_with_start<V: Ord + Copy, E: Ord + Add + Copy>(
  21. graph: &Graph<V, E>,
  22. start: V,
  23. ) -> Graph<V, E> {
  24. // will contain the MST
  25. let mut mst: Graph<V, E> = Graph::new();
  26. // a priority queue based on a binary heap, used to get the cheapest edge
  27. // the elements are an edge: the cost, destination and source
  28. let mut prio = BinaryHeap::new();
  29. mst.insert(start, BTreeMap::new());
  30. for (v, c) in &graph[&start] {
  31. // the heap is a max heap, we have to use Reverse when adding to simulate a min heap
  32. prio.push(Reverse((*c, v, start)));
  33. }
  34. while let Some(Reverse((dist, t, prev))) = prio.pop() {
  35. // the destination of the edge has already been seen
  36. if mst.contains_key(t) {
  37. continue;
  38. }
  39. // the destination is a new vertex
  40. add_edge(&mut mst, prev, *t, dist);
  41. for (v, c) in &graph[t] {
  42. if !mst.contains_key(v) {
  43. prio.push(Reverse((*c, v, *t)));
  44. }
  45. }
  46. }
  47. mst
  48. }
  49. #[cfg(test)]
  50. mod tests {
  51. use super::{add_edge, prim, Graph};
  52. use std::collections::BTreeMap;
  53. #[test]
  54. fn empty() {
  55. assert_eq!(prim::<usize, usize>(&BTreeMap::new()), BTreeMap::new());
  56. }
  57. #[test]
  58. fn single_vertex() {
  59. let mut graph: Graph<usize, usize> = BTreeMap::new();
  60. graph.insert(42, BTreeMap::new());
  61. assert_eq!(prim(&graph), graph);
  62. }
  63. #[test]
  64. fn single_edge() {
  65. let mut graph = BTreeMap::new();
  66. add_edge(&mut graph, 42, 666, 12);
  67. assert_eq!(prim(&graph), graph);
  68. }
  69. #[test]
  70. fn tree_1() {
  71. let mut graph = BTreeMap::new();
  72. add_edge(&mut graph, 0, 1, 10);
  73. add_edge(&mut graph, 0, 2, 11);
  74. add_edge(&mut graph, 2, 3, 12);
  75. add_edge(&mut graph, 2, 4, 13);
  76. add_edge(&mut graph, 1, 5, 14);
  77. add_edge(&mut graph, 1, 6, 15);
  78. add_edge(&mut graph, 3, 7, 16);
  79. assert_eq!(prim(&graph), graph);
  80. }
  81. #[test]
  82. fn tree_2() {
  83. let mut graph = BTreeMap::new();
  84. add_edge(&mut graph, 1, 2, 11);
  85. add_edge(&mut graph, 2, 3, 12);
  86. add_edge(&mut graph, 2, 4, 13);
  87. add_edge(&mut graph, 4, 5, 14);
  88. add_edge(&mut graph, 4, 6, 15);
  89. add_edge(&mut graph, 6, 7, 16);
  90. assert_eq!(prim(&graph), graph);
  91. }
  92. #[test]
  93. fn tree_3() {
  94. let mut graph = BTreeMap::new();
  95. for i in 1..100 {
  96. add_edge(&mut graph, i, 2 * i, i);
  97. add_edge(&mut graph, i, 2 * i + 1, -i);
  98. }
  99. assert_eq!(prim(&graph), graph);
  100. }
  101. #[test]
  102. fn graph_1() {
  103. let mut graph = BTreeMap::new();
  104. add_edge(&mut graph, 'a', 'b', 6);
  105. add_edge(&mut graph, 'a', 'c', 7);
  106. add_edge(&mut graph, 'a', 'e', 2);
  107. add_edge(&mut graph, 'a', 'f', 3);
  108. add_edge(&mut graph, 'b', 'c', 5);
  109. add_edge(&mut graph, 'c', 'e', 5);
  110. add_edge(&mut graph, 'd', 'e', 4);
  111. add_edge(&mut graph, 'd', 'f', 1);
  112. add_edge(&mut graph, 'e', 'f', 2);
  113. let mut ans = BTreeMap::new();
  114. add_edge(&mut ans, 'd', 'f', 1);
  115. add_edge(&mut ans, 'e', 'f', 2);
  116. add_edge(&mut ans, 'a', 'e', 2);
  117. add_edge(&mut ans, 'b', 'c', 5);
  118. add_edge(&mut ans, 'c', 'e', 5);
  119. assert_eq!(prim(&graph), ans);
  120. }
  121. #[test]
  122. fn graph_2() {
  123. let mut graph = BTreeMap::new();
  124. add_edge(&mut graph, 1, 2, 6);
  125. add_edge(&mut graph, 1, 3, 1);
  126. add_edge(&mut graph, 1, 4, 5);
  127. add_edge(&mut graph, 2, 3, 5);
  128. add_edge(&mut graph, 2, 5, 3);
  129. add_edge(&mut graph, 3, 4, 5);
  130. add_edge(&mut graph, 3, 5, 6);
  131. add_edge(&mut graph, 3, 6, 4);
  132. add_edge(&mut graph, 4, 6, 2);
  133. add_edge(&mut graph, 5, 6, 6);
  134. let mut ans = BTreeMap::new();
  135. add_edge(&mut ans, 1, 3, 1);
  136. add_edge(&mut ans, 4, 6, 2);
  137. add_edge(&mut ans, 2, 5, 3);
  138. add_edge(&mut ans, 2, 3, 5);
  139. add_edge(&mut ans, 3, 6, 4);
  140. assert_eq!(prim(&graph), ans);
  141. }
  142. #[test]
  143. fn graph_3() {
  144. let mut graph = BTreeMap::new();
  145. add_edge(&mut graph, "v1", "v2", 1);
  146. add_edge(&mut graph, "v1", "v3", 3);
  147. add_edge(&mut graph, "v1", "v5", 6);
  148. add_edge(&mut graph, "v2", "v3", 2);
  149. add_edge(&mut graph, "v2", "v4", 3);
  150. add_edge(&mut graph, "v2", "v5", 5);
  151. add_edge(&mut graph, "v3", "v4", 5);
  152. add_edge(&mut graph, "v3", "v6", 2);
  153. add_edge(&mut graph, "v4", "v5", 2);
  154. add_edge(&mut graph, "v4", "v6", 4);
  155. add_edge(&mut graph, "v5", "v6", 1);
  156. let mut ans = BTreeMap::new();
  157. add_edge(&mut ans, "v1", "v2", 1);
  158. add_edge(&mut ans, "v5", "v6", 1);
  159. add_edge(&mut ans, "v2", "v3", 2);
  160. add_edge(&mut ans, "v3", "v6", 2);
  161. add_edge(&mut ans, "v4", "v5", 2);
  162. assert_eq!(prim(&graph), ans);
  163. }
  164. }