use std::collections::HashMap;
#[derive(Debug)]
struct Edge {
from: char,
to: char,
weight: i32,
}
fn bellman_ford(edges: &[Edge], start: char) -> Result<HashMap<char, i32>, String> {
let mut dist = HashMap::new();
// Initialize distances
for edge in edges {
dist.insert(edge.from, i32::MAX);
dist.insert(edge.to, i32::MAX);
}
dist.insert(start, 0);
let vertices: Vec<char> = dist.keys().cloned().collect();
let v_count = vertices.len();
// Relax edges v_count - 1 times
for _ in 0..v_count - 1 {
let mut updated = false;
for edge in edges {
let from_dist = *dist.get(&edge.from).unwrap_or(&i32::MAX);
if from_dist != i32::MAX {
let to_dist = *dist.get(&edge.to).unwrap_or(&i32::MAX);
if from_dist.checked_add(edge.weight).map_or(false, |new_dist| new_dist < to_dist) {
dist.insert(edge.to, from_dist + edge.weight);
updated = true;
}
}
}
if !updated {
break; // No update means shortest paths found
}
}
// Check for negative weight cycles
for edge in edges {
let from_dist = *dist.get(&edge.from).unwrap_or(&i32::MAX);
let to_dist = *dist.get(&edge.to).unwrap_or(&i32::MAX);
if from_dist != i32::MAX && from_dist.checked_add(edge.weight).map_or(false, |new_dist| new_dist < to_dist) {
return Err("Graph contains a negative weight cycle".to_string());
}
}
Ok(dist)
}
fn main() {
let edges = vec![
Edge { from: 'A', to: 'B', weight: -1 },
Edge { from: 'A', to: 'C', weight: 4 },
Edge { from: 'B', to: 'C', weight: 3 },
Edge { from: 'B', to: 'D', weight: 2 },
Edge { from: 'D', to: 'B', weight: 1 },
Edge { from: 'D', to: 'C', weight: -3 },
];
match bellman_ford(&edges, 'A') {
Ok(distances) => {
let mut keys: Vec<_> = distances.keys().cloned().collect();
keys.sort();
for k in keys {
println!("Distance from A to {} is {}", k, distances[&k]);
}
}
Err(e) => println!("Error: {}", e),
}
}
Set distance to start node as zero
for _ in 0..v_count - 1 {
Repeat relaxation for all vertices minus one times
if from_dist + edge.weight < to_dist {
Relax edge if shorter path found
Stop early if no distance updates
if from_dist != i32::MAX && from_dist + edge.weight < to_dist { return Err(...); }
Detect negative weight cycle if further relaxation possible
Distance from A to A is 0
Distance from A to B is -1
Distance from A to C is -2
Distance from A to D is 1