use mut_binary_heap::BinaryHeap;
use std::cmp::Ordering;
#[derive(Copy, Clone, Eq, PartialEq)]
struct Node {
cost: usize,
position: usize,
}
impl Ord for Node {
fn cmp(&self, other: &Self) -> Ordering {
other
.cost
.cmp(&self.cost)
.then_with(|| self.position.cmp(&other.position))
}
}
impl PartialOrd for Node {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
struct Edge {
node: usize,
cost: usize,
}
fn shortest_path(edges: &Vec<Vec<Edge>>, start: usize, goal: usize) -> Option<usize> {
let mut heap: BinaryHeap<usize, Node> = BinaryHeap::new();
heap.push(
start,
Node {
cost: 0,
position: start,
},
);
while let Some(Node { cost, position }) = heap.pop() {
if position == goal {
return Some(cost);
}
for edge in &edges[position] {
let next_cost = cost + edge.cost;
if heap.contains_key(&edge.node) {
let mut node = heap.get_mut(&edge.node).unwrap();
assert_eq!(node.position, edge.node);
if next_cost < node.cost {
node.cost = next_cost;
}
} else {
heap.push(
edge.node,
Node {
cost: next_cost,
position: edge.node,
},
);
}
}
}
None
}
fn main() {
let graph = vec![
vec![Edge { node: 2, cost: 10 }, Edge { node: 1, cost: 1 }],
vec![Edge { node: 3, cost: 2 }],
vec![
Edge { node: 1, cost: 1 },
Edge { node: 3, cost: 3 },
Edge { node: 4, cost: 1 },
],
vec![Edge { node: 0, cost: 7 }, Edge { node: 4, cost: 2 }],
vec![],
];
assert_eq!(shortest_path(&graph, 0, 1), Some(1));
assert_eq!(shortest_path(&graph, 0, 3), Some(3));
assert_eq!(shortest_path(&graph, 3, 0), Some(7));
assert_eq!(shortest_path(&graph, 0, 4), Some(5));
assert_eq!(shortest_path(&graph, 4, 0), None);
}