use std::collections::BinaryHeap; use std::cmp::Ordering; #[derive(Copy, Clone, Eq, PartialEq)] struct State { cost: usize, position: usize, } impl Ord for State { fn cmp(&self, other: &Self) -> Ordering { other.cost.cmp(&self.cost) .then_with(|| self.position.cmp(&other.position)) } } impl PartialOrd for State { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) } } fn dijkstra(adj_list: &Vec<Vec<(usize, usize)>>, start: usize) -> Vec<usize> { let mut dist = vec![usize::MAX; adj_list.len()]; let mut heap = BinaryHeap::new(); dist[start] = 0; heap.push(State { cost: 0, position: start }); while let Some(State { cost, position }) = heap.pop() { if cost > dist[position] { continue; } for &(neighbor, weight) in &adj_list[position] { let next = State { cost: cost + weight, position: neighbor }; if next.cost < dist[neighbor] { dist[neighbor] = next.cost; heap.push(next); } } } dist } fn main() { let graph = vec![ vec![(1, 2), (2, 4)], vec![(2, 1), (3, 7)], vec![(3, 3)], vec![], ]; let distances = dijkstra(&graph, 0); println!("{:?}", distances); }
The shortest distances from node 0 are: to node 1 is 2, to node 2 is 3 (via node 1), and to node 3 is 6 (via nodes 1 and 2).
The priority queue ensures the algorithm always processes the node with the smallest known distance next, which is essential for correctness and efficiency.
fn dijkstra(adj_list: &Vec<Vec<(usize, usize)>>, start: usize) -> Vec<usize> {
let mut dist = vec![usize::MAX; adj_list.len()];
let mut heap = BinaryHeap::new();
dist[start] = 0;
heap.push(State { cost: 0, position: start });
while let Some(State { cost, position }) = heap.pop() {
if cost > dist[position] {
continue;
}
for &(neighbor, weight) in &adj_list[position] {
let next = State { cost: cost + weight, position: neighbor };
if next.cost < dist[neighbor] {
dist[neighbor] = next.cost;
heap.push(next);
}
}
}
dist
}The condition 'if cost < dist[position]' is incorrect. It should be 'if cost > dist[position]' to skip outdated entries. This bug causes the algorithm to process nodes with outdated distances, leading to wrong results.
fn main() {
let graph = vec![
vec![(1, 10), (2, 3)],
vec![(2, 1), (3, 2)],
vec![(1, 4), (3, 8), (4, 2)],
vec![(4, 7)],
vec![],
];
let distances = dijkstra(&graph, 0);
println!("{:?}", distances);
}Node 4 is reachable via node 2 with total cost 5 (3 + 2). Distances are [0,7,3,9,5].
Dijkstra's algorithm assumes that once a node is visited with the smallest distance, no shorter path to it exists. Negative edges can violate this assumption by allowing shorter paths after visiting.
