1use crate::graph::*;
4use std::{cmp::Reverse, collections::BinaryHeap};
5
6pub fn prim<E: EdgeTrait>(g: &Graph<Undirected, E>) -> Option<Vec<&E>>
11where
12 E::Weight: Ord,
13{
14 let n = g.len();
15 let mut visit = vec![false; n];
16 let mut ret = vec![];
17 let mut heap = BinaryHeap::new();
18
19 visit[0] = true;
20 for (index, e) in g.nodes[0].edges.iter().enumerate() {
21 heap.push(Reverse((e.weight(), e.from(), index)));
22 }
23
24 while let Some(Reverse((_, from, index))) = heap.pop() {
25 let e = &g.nodes[from].edges[index];
26 if visit[e.from()] == visit[e.to()] {
27 continue;
28 }
29
30 let i = if visit[e.from()] { e.to() } else { e.from() };
31 for (index, e) in g.nodes[i].edges.iter().enumerate() {
32 heap.push(Reverse((e.weight(), e.from(), index)));
33 }
34
35 visit[i] = true;
36
37 ret.push(e);
38 }
39
40 (ret.len() == n - 1).then_some(ret)
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn test() {
49 let mut g = Graph::<Undirected, _>::new(6);
50 g.extend(
51 vec![
52 (0, 1, 1),
53 (0, 2, 3),
54 (1, 2, 1),
55 (1, 3, 7),
56 (2, 4, 1),
57 (1, 4, 3),
58 (3, 4, 1),
59 (3, 5, 1),
60 (4, 5, 6),
61 ]
62 .into_iter()
63 .map(|(u, v, w)| Edge::new(u, v, w, ())),
64 );
65
66 let ans = prim(&g).unwrap().iter().map(|e| e.weight).sum::<i32>();
67
68 assert_eq!(ans, 5);
69 }
70}