1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use crate::algo::graph::{Edge, WeightedAdjacencyList};
use ordered_float::OrderedFloat;
use priority_queue::PriorityQueue;
impl WeightedAdjacencyList {
pub fn dijkstra(&self, start: usize, end: usize) -> Option<(f32, Vec<usize>)> {
let n = self.vertices_count();
let mut dists = vec![f32::INFINITY; n];
let mut prev = vec![None; n];
let mut vis = vec![false; n];
let mut pq = PriorityQueue::with_capacity(self.vertices_count());
pq.push(start, OrderedFloat::from(-0f32));
dists[start] = 0f32;
while let Some((node, cur_dist)) = pq.pop() {
if node == end {
break;
};
let cur_dist = -cur_dist.into_inner();
vis[node] = true;
let dist = &mut dists[node];
if *dist < cur_dist {
continue;
}
*dist = cur_dist;
for &Edge { to, cost } in &self[node] {
if !vis[to] {
let new_dist = cur_dist + cost;
if new_dist < dists[to] {
prev[to] = Some(node);
dists[to] = new_dist;
pq.push(to, (-new_dist).into());
}
}
}
}
if prev[end].is_none() {
if start == end {
Some((dists[start], vec![start]))
} else {
None
}
} else {
let mut path = vec![end];
let mut i = end;
while let Some(node) = prev[i] {
path.push(node);
i = node;
}
path.reverse();
Some((dists[end], path))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dijkstra() {
let graph = WeightedAdjacencyList::new_directed(
6,
&[
(0, 1, 5.),
(0, 2, 1.),
(1, 2, 2.),
(2, 1, 3.),
(1, 3, 3.),
(1, 4, 20.),
(2, 4, 12.),
(3, 2, 3.),
(3, 4, 2.),
(3, 5, 6.),
(3, 4, 2.),
(4, 5, 1.),
],
);
let (dist, path) = graph.dijkstra(0, 5).unwrap();
assert_eq!(&path, &[0, 2, 1, 3, 4, 5]);
assert_eq!(dist, 10.);
assert_eq!(graph.dijkstra(1, 1).unwrap(), (0.0, vec![1]));
}
}