use std::cmp::min; #[derive(Debug)] pub struct Graph { pub n_nodes: usize, pub n_edges: usize, pub nodes: Vec, } #[derive(Debug)] pub struct Node { pub id: usize, pub edges: Vec, } #[derive(Debug)] pub struct Edge { pub source: usize, pub target: usize, pub length: i64, } pub fn floyd_warshall(g: Graph) -> Option { let n = g.n_nodes; let mut a: Vec> = 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) }