#![allow(dead_code)]
use std::collections::BinaryHeap;
use std::cmp::Reverse;
#[derive(Debug, Clone)]
pub struct WeightedEdge {
pub to: usize,
pub weight: f64,
}
#[derive(Debug, Default, Clone)]
pub struct WeightedGraph {
adj: Vec<Vec<WeightedEdge>>,
}
impl WeightedGraph {
pub fn new(n: usize) -> Self {
WeightedGraph { adj: vec![vec![]; n] }
}
pub fn vertex_count(&self) -> usize {
self.adj.len()
}
pub fn add_edge(&mut self, u: usize, v: usize, weight: f64) {
self.adj[u].push(WeightedEdge { to: v, weight });
}
pub fn add_undirected_edge(&mut self, u: usize, v: usize, weight: f64) {
self.add_edge(u, v, weight);
self.add_edge(v, u, weight);
}
pub fn degree(&self, u: usize) -> usize {
self.adj[u].len()
}
pub fn neighbours(&self, u: usize) -> &[WeightedEdge] {
&self.adj[u]
}
pub fn dijkstra(&self, src: usize) -> Vec<f64> {
let n = self.adj.len();
let mut dist = vec![f64::INFINITY; n];
dist[src] = 0.0;
let mut heap: BinaryHeap<Reverse<(u64, usize)>> = BinaryHeap::new();
heap.push(Reverse((0, src)));
while let Some(Reverse((d_raw, u))) = heap.pop() {
let d = d_raw as f64 / 1e9;
if d > dist[u] { continue; }
for e in &self.adj[u] {
let nd = dist[u] + e.weight;
if nd < dist[e.to] {
dist[e.to] = nd;
heap.push(Reverse(((nd * 1e9) as u64, e.to)));
}
}
}
dist
}
pub fn edge_count(&self) -> usize {
self.adj.iter().map(|a| a.len()).sum()
}
pub fn has_self_loop(&self) -> bool {
for (u, edges) in self.adj.iter().enumerate() {
if edges.iter().any(|e| e.to == u) {
return true;
}
}
false
}
}
pub fn new_weighted_graph(n: usize) -> WeightedGraph {
WeightedGraph::new(n)
}
pub fn wg_add_edge(g: &mut WeightedGraph, u: usize, v: usize, w: f64) {
g.add_edge(u, v, w);
}
pub fn wg_add_undirected(g: &mut WeightedGraph, u: usize, v: usize, w: f64) {
g.add_undirected_edge(u, v, w);
}
pub fn wg_dijkstra(g: &WeightedGraph, src: usize) -> Vec<f64> {
g.dijkstra(src)
}
pub fn wg_vertex_count(g: &WeightedGraph) -> usize {
g.vertex_count()
}
pub fn wg_edge_count(g: &WeightedGraph) -> usize {
g.edge_count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vertex_count() {
let g = new_weighted_graph(5);
assert_eq!(wg_vertex_count(&g), 5 );
}
#[test]
fn test_add_edge() {
let mut g = new_weighted_graph(3);
wg_add_edge(&mut g, 0, 1, 2.0);
assert_eq!(wg_edge_count(&g), 1 );
}
#[test]
fn test_undirected_edge() {
let mut g = new_weighted_graph(3);
wg_add_undirected(&mut g, 0, 1, 5.0);
assert_eq!(wg_edge_count(&g), 2 );
}
#[test]
fn test_dijkstra_simple() {
let mut g = new_weighted_graph(3);
wg_add_edge(&mut g, 0, 1, 1.0);
wg_add_edge(&mut g, 1, 2, 2.0);
let d = wg_dijkstra(&g, 0);
assert!((d[2] - 3.0).abs() < 0.01 );
}
#[test]
fn test_dijkstra_unreachable() {
let g = new_weighted_graph(3);
let d = wg_dijkstra(&g, 0);
assert!(d[1].is_infinite() );
}
#[test]
fn test_dijkstra_shorter_path() {
let mut g = new_weighted_graph(4);
wg_add_edge(&mut g, 0, 1, 10.0);
wg_add_edge(&mut g, 0, 2, 1.0);
wg_add_edge(&mut g, 2, 1, 1.0);
let d = wg_dijkstra(&g, 0);
assert!((d[1] - 2.0).abs() < 0.01 );
}
#[test]
fn test_degree() {
let mut g = new_weighted_graph(4);
wg_add_edge(&mut g, 0, 1, 1.0);
wg_add_edge(&mut g, 0, 2, 2.0);
assert_eq!(g.degree(0), 2 );
}
#[test]
fn test_no_self_loop() {
let mut g = new_weighted_graph(3);
wg_add_edge(&mut g, 0, 1, 1.0);
assert!(!g.has_self_loop() );
}
#[test]
fn test_self_loop_detected() {
let mut g = new_weighted_graph(2);
wg_add_edge(&mut g, 0, 0, 1.0);
assert!(g.has_self_loop() );
}
#[test]
fn test_dijkstra_source_zero() {
let g = new_weighted_graph(3);
let d = wg_dijkstra(&g, 0);
assert_eq!(d[0], 0.0 );
}
}