algos/src/floyd_warshall.rs

78 lines
1.4 KiB
Rust

use std::cmp::min;
#[derive(Debug)]
pub struct Graph {
pub n_nodes: usize,
pub n_edges: usize,
pub nodes: Vec<Node>,
}
#[derive(Debug)]
pub struct Node {
pub id: usize,
pub edges: Vec<Edge>,
}
#[derive(Debug)]
pub struct Edge {
pub source: usize,
pub target: usize,
pub length: i64,
}
pub fn floyd_warshall(g: Graph) -> Option<i64> {
let n = g.n_nodes;
let mut a: Vec<Vec<i64>> = vec![vec![std::i64::MAX; n]; n];
// nodes have lengths of 0 to themself
for i in 0..n {
a[i][i] = 0;
}
// nodes that are connected get the length of their edge
for n in &g.nodes {
for e in &n.edges {
a[e.source][e.target] = e.length;
}
}
// main workloop
for k in 0..n {
let mut new_a = a.to_vec();
for i in 0..n {
for j in 0..n {
let case_1 = a[i][j];
let case_2 = match a[i][k].checked_add(a[k][j]) {
Some(v) => v,
None => std::i64::MAX,
};
new_a[i][j] = min(case_1, case_2);
}
}
a = new_a;
}
// node to itself is negative means we have negative cost cycles
for i in 0..n {
if a[i][i] < 0 {
return None;
}
}
// find min path from v to u
let mut r = std::i64::MAX;
for i in 0..n {
for j in 0..n {
if i != j {
let d = a[i][j];
if d < r {
r = d;
}
}
}
}
Some(r)
}