contest_algorithms/graph/
util.rs

1use super::{DisjointSets, Graph};
2use crate::graph::AdjListIterator;
3use std::cmp::Reverse;
4
5impl Graph {
6    /// Finds the sequence of edges in an Euler path starting from u, assuming
7    /// it exists and that the graph is directed. Undefined behavior if this
8    /// precondition is violated. To extend this to undirected graphs, maintain
9    /// a visited array to skip the reverse edge.
10    pub fn euler_path(&self, u: usize) -> Vec<usize> {
11        let mut adj_iters = (0..self.num_v())
12            .map(|u| self.adj_list(u))
13            .collect::<Vec<_>>();
14        let mut edges = Vec::with_capacity(self.num_e());
15        self.euler_recurse(u, &mut adj_iters, &mut edges);
16        edges.reverse();
17        edges
18    }
19
20    // Helper function used by euler_path. Note that we can't use a for-loop
21    // that would consume the adjacency list as recursive calls may need it.
22    fn euler_recurse(&self, u: usize, adj: &mut [AdjListIterator], edges: &mut Vec<usize>) {
23        while let Some((e, v)) = adj[u].next() {
24            self.euler_recurse(v, adj, edges);
25            edges.push(e);
26        }
27    }
28
29    /// Kruskal's minimum spanning tree algorithm on an undirected graph.
30    pub fn min_spanning_tree(&self, weights: &[i64]) -> Vec<usize> {
31        assert_eq!(self.num_e(), 2 * weights.len());
32        let mut edges = (0..weights.len()).collect::<Vec<_>>();
33        edges.sort_unstable_by_key(|&e| weights[e]);
34
35        let mut components = DisjointSets::new(self.num_v());
36        edges
37            .into_iter()
38            .filter(|&e| components.merge(self.endp[2 * e], self.endp[2 * e + 1]))
39            .collect()
40    }
41
42    // Single-source shortest paths on a directed graph with non-negative weights
43    pub fn dijkstra(&self, weights: &[u64], u: usize) -> Vec<u64> {
44        assert_eq!(self.num_e(), weights.len());
45        let mut dist = vec![u64::max_value(); weights.len()];
46        let mut heap = std::collections::BinaryHeap::new();
47
48        dist[u] = 0;
49        heap.push((Reverse(0), 0));
50        while let Some((Reverse(dist_u), u)) = heap.pop() {
51            if dist[u] == dist_u {
52                for (e, v) in self.adj_list(u) {
53                    let dist_v = dist_u + weights[e];
54                    if dist[v] > dist_v {
55                        dist[v] = dist_v;
56                        heap.push((Reverse(dist_v), v));
57                    }
58                }
59            }
60        }
61        dist
62    }
63
64    pub fn dfs(&self, root: usize) -> DfsIterator {
65        let mut visited = vec![false; self.num_v()];
66        visited[root] = true;
67        let adj_iters = (0..self.num_v())
68            .map(|u| self.adj_list(u))
69            .collect::<Vec<_>>();
70
71        DfsIterator {
72            visited,
73            stack: vec![root],
74            adj_iters,
75        }
76    }
77}
78
79pub struct DfsIterator<'a> {
80    visited: Vec<bool>,
81    stack: Vec<usize>,
82    adj_iters: Vec<AdjListIterator<'a>>,
83}
84
85impl<'a> Iterator for DfsIterator<'a> {
86    type Item = (usize, usize);
87
88    /// Returns next edge and vertex in the depth-first traversal
89    // Refs: https://www.geeksforgeeks.org/iterative-depth-first-traversal/
90    //       https://en.wikipedia.org/wiki/Depth-first_search
91    fn next(&mut self) -> Option<Self::Item> {
92        loop {
93            let &u = self.stack.last()?;
94            while let Some((e, v)) = self.adj_iters[u].next() {
95                if !self.visited[v] {
96                    self.visited[v] = true;
97                    self.stack.push(v);
98                    return Some((e, v));
99                }
100            }
101            self.stack.pop();
102        }
103    }
104}
105
106#[cfg(test)]
107mod test {
108    use super::*;
109
110    #[test]
111    fn test_euler() {
112        let mut graph = Graph::new(3, 4);
113        graph.add_edge(0, 1);
114        graph.add_edge(1, 0);
115        graph.add_edge(1, 2);
116        graph.add_edge(2, 1);
117
118        assert_eq!(graph.euler_path(0), vec![0, 2, 3, 1]);
119    }
120
121    #[test]
122    fn test_min_spanning_tree() {
123        let mut graph = Graph::new(3, 6);
124        graph.add_undirected_edge(0, 1);
125        graph.add_undirected_edge(1, 2);
126        graph.add_undirected_edge(2, 0);
127        let weights = [7, 3, 5];
128
129        let mst = graph.min_spanning_tree(&weights);
130        let mst_cost = mst.iter().map(|&e| weights[e]).sum::<i64>();
131        assert_eq!(mst, vec![1, 2]);
132        assert_eq!(mst_cost, 8);
133    }
134
135    #[test]
136    fn test_dijkstra() {
137        let mut graph = Graph::new(3, 3);
138        graph.add_edge(0, 1);
139        graph.add_edge(1, 2);
140        graph.add_edge(2, 0);
141        let weights = [7, 3, 5];
142
143        let dist = graph.dijkstra(&weights, 0);
144        assert_eq!(dist, vec![0, 7, 10]);
145    }
146
147    #[test]
148    fn test_dfs() {
149        let mut graph = Graph::new(4, 6);
150        graph.add_edge(0, 2);
151        graph.add_edge(2, 0);
152        graph.add_edge(1, 2);
153        graph.add_edge(0, 1);
154        graph.add_edge(3, 3);
155        graph.add_edge(2, 3);
156
157        let dfs_root = 2;
158        let dfs_traversal = std::iter::once(dfs_root)
159            .chain(graph.dfs(dfs_root).map(|(_, v)| v))
160            .collect::<Vec<_>>();
161
162        assert_eq!(dfs_traversal, vec![2, 3, 0, 1]);
163    }
164
165    #[test]
166    fn test_dfs2() {
167        let mut graph = Graph::new(5, 6);
168        graph.add_edge(0, 2);
169        graph.add_edge(2, 1);
170        graph.add_edge(1, 0);
171        graph.add_edge(0, 3);
172        graph.add_edge(3, 4);
173        graph.add_edge(4, 0);
174
175        let dfs_root = 0;
176        let dfs_traversal = std::iter::once(dfs_root)
177            .chain(graph.dfs(dfs_root).map(|(_, v)| v))
178            .collect::<Vec<_>>();
179
180        assert_eq!(dfs_traversal, vec![0, 3, 4, 2, 1]);
181    }
182
183    #[test]
184    fn test_dfs_space_complexity() {
185        let num_v = 20;
186        let mut graph = Graph::new(num_v, 0);
187        for i in 0..num_v {
188            for j in 0..num_v {
189                graph.add_undirected_edge(i, j);
190            }
191        }
192
193        let dfs_root = 7;
194        let mut dfs_search = graph.dfs(dfs_root);
195        let mut dfs_check = vec![dfs_root];
196        for _ in 1..num_v {
197            dfs_check.push(dfs_search.next().unwrap().1);
198            assert!(dfs_search.stack.len() <= num_v + 1);
199        }
200
201        dfs_check.sort();
202        dfs_check.dedup();
203        assert_eq!(0, dfs_check[0]);
204        assert_eq!(num_v, dfs_check.len());
205        assert_eq!(num_v - 1, dfs_check[num_v - 1]);
206    }
207}