1pub mod bfs;
10pub mod bipartite_check;
11pub mod dfs;
12pub mod eulerian_path;
13pub mod minimum_spanning_tree;
14pub mod network_flow;
15pub mod shortest_path;
16pub mod tarjan_scc;
17pub mod topological_sort;
18pub mod tree;
19
20use std::fmt;
21
22#[derive(Debug, Copy, Clone)]
25pub struct Edge {
26 pub to: usize,
27 pub weight: f64,
28}
29impl Edge {
30 pub fn new(to: usize, weight: f64) -> Self {
32 Self { to, weight }
33 }
34}
35
36#[derive(Debug)]
42pub struct WeightedAdjacencyList {
43 inner: Vec<Vec<Edge>>,
44}
45
46impl WeightedAdjacencyList {
47 pub fn with_size(n: usize) -> Self {
49 Self {
50 inner: vec![vec![]; n],
51 }
52 }
53 pub fn is_empty(&self) -> bool {
55 self.inner.is_empty()
56 }
57 pub fn add_directed_edge(&mut self, u: usize, v: usize, weight: f64) {
59 self.inner[u].push(Edge::new(v, weight))
60 }
61 pub fn add_undirected_edge(&mut self, u: usize, v: usize, weight: f64) {
63 self.add_directed_edge(u, v, weight);
64 self.add_directed_edge(v, u, weight);
65 }
66 pub fn new_directed(size: usize, edges: &[(usize, usize, f64)]) -> Self {
67 let mut graph = Self::with_size(size);
68 for &(a, b, c) in edges.iter() {
69 graph.add_directed_edge(a, b, c);
70 }
71 graph
72 }
73 pub fn new_undirected(size: usize, edges: &[(usize, usize, f64)]) -> Self {
74 let mut graph = Self::with_size(size);
75 for &(a, b, c) in edges.iter() {
76 graph.add_undirected_edge(a, b, c);
77 }
78 graph
79 }
80 pub fn new_directed_unweighted(size: usize, edges: &[[usize; 2]]) -> Self {
81 let mut graph = Self::with_size(size);
82 for &[a, b] in edges.iter() {
83 graph.add_directed_edge(a, b, 1.);
84 }
85 graph
86 }
87 pub fn new_undirected_unweighted(size: usize, edges: &[[usize; 2]]) -> Self {
88 let mut graph = Self::with_size(size);
89 for &[a, b] in edges.iter() {
90 graph.add_undirected_edge(a, b, 1.);
91 }
92 graph
93 }
94 pub fn edges(&self) -> impl Iterator<Item = (usize, usize, f64)> + '_ {
97 self.inner
98 .iter()
99 .enumerate()
100 .flat_map(|(a, edges)| edges.iter().map(move |b| (a, b.to, b.weight)))
101 }
102 pub fn edge_count(&self) -> usize {
104 self.edges().count()
105 }
106 pub fn nodes(&self) -> impl Iterator<Item = (usize, &Vec<Edge>)> {
109 self.inner.iter().enumerate()
110 }
111 pub fn node_count(&self) -> usize {
113 self.inner.len()
114 }
115}
116
117impl std::ops::Index<usize> for WeightedAdjacencyList {
119 type Output = Vec<Edge>;
120 fn index(&self, index: usize) -> &Self::Output {
121 &self.inner[index]
122 }
123}
124
125#[derive(Debug)]
129pub struct UnweightedAdjacencyList {
130 inner: Vec<Vec<usize>>,
131}
132
133impl UnweightedAdjacencyList {
134 pub fn with_size(n: usize) -> Self {
136 Self {
137 inner: vec![vec![]; n],
138 }
139 }
140 pub fn is_empty(&self) -> bool {
141 self.inner.is_empty()
142 }
143 pub fn add_directed_edge(&mut self, u: usize, v: usize) {
145 self.inner[u].push(v)
146 }
147 pub fn add_undirected_edge(&mut self, u: usize, v: usize) {
149 self.add_directed_edge(u, v);
150 self.add_directed_edge(v, u);
151 }
152 pub fn new_directed(size: usize, edges: &[[usize; 2]]) -> Self {
153 let mut graph = Self::with_size(size);
154 for &[a, b] in edges.iter() {
155 graph.add_directed_edge(a, b);
156 }
157 graph
158 }
159 pub fn new_undirected(size: usize, edges: &[[usize; 2]]) -> Self {
160 let mut graph = Self::with_size(size);
161 for &[a, b] in edges.iter() {
162 graph.add_undirected_edge(a, b);
163 }
164 graph
165 }
166 pub fn edges(&self) -> impl Iterator<Item = [usize; 2]> + '_ {
169 self.inner
170 .iter()
171 .enumerate()
172 .flat_map(|(a, edges)| edges.iter().map(move |&b| [a, b]))
173 }
174 pub fn edge_count(&self) -> usize {
176 self.edges().count()
177 }
178 pub fn nodes(&self) -> impl Iterator<Item = (usize, &Vec<usize>)> {
181 self.inner.iter().enumerate()
182 }
183 pub fn node_count(&self) -> usize {
185 self.inner.len()
186 }
187}
188
189impl std::ops::Index<usize> for UnweightedAdjacencyList {
191 type Output = Vec<usize>;
192 fn index(&self, index: usize) -> &Self::Output {
193 &self.inner[index]
194 }
195}
196
197pub struct WeightedAdjacencyMatrix {
204 inner: Vec<Vec<f64>>,
205}
206
207impl WeightedAdjacencyMatrix {
208 #[allow(clippy::needless_range_loop)]
209 pub fn with_size(n: usize) -> Self {
210 let mut inner = vec![vec![f64::INFINITY; n]; n];
212 for i in 0..n {
214 inner[i][i] = 0.;
215 }
216 Self { inner }
217 }
218 pub fn node_count(&self) -> usize {
220 self.inner.len()
221 }
222 pub fn from_adjacency_list(inp: &WeightedAdjacencyList) -> Self {
224 let mut res = Self::with_size(inp.node_count());
225 for (from, edges) in inp.nodes() {
226 for &Edge { to, weight } in edges {
227 res.inner[from][to] = weight;
228 }
229 }
230 res
231 }
232 pub fn from_inner(matrix: Vec<Vec<f64>>) -> Self {
234 Self { inner: matrix }
235 }
236}
237
238impl std::ops::Index<usize> for WeightedAdjacencyMatrix {
241 type Output = Vec<f64>;
242 fn index(&self, index: usize) -> &Self::Output {
243 &self.inner[index]
244 }
245}
246
247impl From<WeightedAdjacencyList> for WeightedAdjacencyMatrix {
249 fn from(inp: WeightedAdjacencyList) -> Self {
250 Self::from_adjacency_list(&inp)
251 }
252}
253
254impl From<Vec<Vec<f64>>> for WeightedAdjacencyMatrix {
256 fn from(matrix: Vec<Vec<f64>>) -> Self {
257 Self::from_inner(matrix)
258 }
259}
260
261impl fmt::Display for WeightedAdjacencyMatrix {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 let n = self.node_count();
265 write!(f, " ")?;
266 for i in 0..n {
267 write!(f, "{:>2} ", i)?;
268 }
269 writeln!(f)?;
270 for i in 0..n {
271 write!(f, "{:>2} ", i)?;
272 for j in 0..n {
273 let x = self[i][j];
274 if x == f64::INFINITY {
275 write!(f, " ∞ ")?;
276 } else if x == f64::NEG_INFINITY {
277 write!(f, "-∞ ")?;
278 } else {
279 write!(f, "{:>2} ", self[i][j])?;
280 }
281 }
282 writeln!(f)?;
283 }
284 Ok(())
285 }
286}
287
288impl fmt::Display for WeightedAdjacencyList {
291 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292 writeln!(f, "{}", WeightedAdjacencyMatrix::from_adjacency_list(self))
293 }
294}
295
296#[derive(Debug)]
305pub struct WeightedUndirectedAdjacencyMatrixCondensed {
306 inner: Vec<f64>,
307 n: usize,
308}
309
310impl WeightedUndirectedAdjacencyMatrixCondensed {
311 pub fn new(node_count: usize) -> Self {
312 Self {
313 inner: vec![f64::INFINITY; node_count * (node_count - 1) / 2],
314 n: node_count,
315 }
316 }
317 pub fn from_adjacency_list(inp: &WeightedAdjacencyList) -> Self {
326 let n = inp.node_count();
327 let mut m = Self {
328 inner: vec![f64::INFINITY; n * (n - 1) / 2],
329 n,
330 };
331 for (i, j, weight) in inp.edges() {
332 let w = &mut m[(i, j)];
333 if w.is_finite() {
334 assert!(
335 (*w - weight).abs() < f64::EPSILON,
336 "Graph contains directed edge(s)!"
337 );
338 } else {
339 *w = weight;
340 }
341 }
342 m
343 }
344 pub fn from_slice(inp: &[f64]) -> Self {
346 assert!(!inp.is_empty(), "Inpud cannot be empty.");
347 let mut n = 2;
348 loop {
349 n += 1;
350 let len = n * (n - 1) / 2;
351 if len == inp.len() {
352 return Self {
353 inner: inp.to_owned(),
354 n,
355 };
356 }
357 if len > inp.len() {
358 panic!("Invalid input length.")
359 }
360 }
361 }
362 pub fn edges(&self) -> impl Iterator<Item = (usize, usize, f64)> + '_ {
366 (0..self.n - 1)
367 .flat_map(move |i| (i + 1..self.n).map(move |j| (i, j)))
368 .zip(self.inner.iter())
369 .map(|((i, j), w)| (i, j, *w))
370 }
371 pub fn node_count(&self) -> usize {
373 self.n
374 }
375 pub fn resized(&self, new_node_count: usize) -> Self {
376 let mut new = Self::new(new_node_count);
377 for (i, j, weight) in self.edges() {
378 if i < new_node_count && j < new_node_count {
379 new[(i, j)] = weight;
380 }
381 }
382 new
383 }
384}
385
386impl std::ops::Index<(usize, usize)> for WeightedUndirectedAdjacencyMatrixCondensed {
390 type Output = f64;
391
392 fn index(&self, (i, j): (usize, usize)) -> &Self::Output {
393 use std::cmp::Ordering::*;
394 assert!(i < self.n && j < self.n, "Index out of bound.");
395 match i.cmp(&j) {
396 Less => {
397 let (mut _i, mut j_, mut j, mut k) = (i, self.n - 1, j - 1, 0);
398 while _i > 0 {
399 k += j_;
400 j_ -= 1;
401 j -= 1;
402 _i -= 1;
403 }
404 k += j;
405 &self.inner[k]
406 }
407 Greater => self.index((j, i)),
408 Equal => &0.,
409 }
410 }
411}
412impl std::ops::IndexMut<(usize, usize)> for WeightedUndirectedAdjacencyMatrixCondensed {
413 fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut Self::Output {
414 use std::cmp::Ordering::*;
415 match i.cmp(&j) {
416 Less => {
417 let (mut _i, mut j_, mut j, mut k) = (i, self.n - 1, j - 1, 0);
418 while _i > 0 {
419 k += j_;
420 j_ -= 1;
421 j -= 1;
422 _i -= 1;
423 }
424 k += j;
425 &mut self.inner[k]
426 }
427 Greater => self.index_mut((j, i)),
428 Equal => panic!("Not allowed to assign a weight from a vetex to itself!"),
429 }
430 }
431}
432
433impl From<WeightedAdjacencyList> for WeightedUndirectedAdjacencyMatrixCondensed {
434 fn from(inp: WeightedAdjacencyList) -> Self {
435 Self::from_adjacency_list(&inp)
436 }
437}
438
439impl fmt::Display for WeightedUndirectedAdjacencyMatrixCondensed {
440 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441 let n = self.node_count();
442 write!(f, " ")?;
443 for i in 1..n {
444 write!(f, "{:>5} ", i)?;
445 }
446 writeln!(f)?;
447 for i in 0..n - 1 {
448 write!(f, "{:>2} ", i)?;
449 for _ in 0..i {
450 write!(f, " ")?;
451 }
452 for j in i + 1..n {
453 let x = self[(i, j)];
454 if x == f64::INFINITY {
455 write!(f, " ∞ ")?;
456 } else if x == f64::NEG_INFINITY {
457 write!(f, " -∞ ")?;
458 } else {
459 write!(f, " {:>4.2}", x)?;
460 }
461 }
462 writeln!(f)?;
463 }
464 Ok(())
465 }
466}
467
468#[cfg(test)]
469mod tests {
470
471 use super::*;
472 #[test]
473 fn test_graph_adj_list() {
474 let mut edges = vec![[0, 1], [1, 2], [0, 2], [1, 1]];
475 let g = UnweightedAdjacencyList::new_directed(3, &edges);
476 for edge in g.edges() {
477 let i = edges.iter().position(|e| *e == edge).unwrap();
478 edges.remove(i);
479 }
480 assert!(edges.is_empty());
481 }
482
483 #[test]
484 fn test_weighted_undirected_condensed() {
485 let edges = &[
486 (0, 1, 1.),
487 (0, 2, 2.),
488 (0, 3, 3.),
489 (1, 2, 4.),
490 (1, 3, 5.),
491 (2, 3, 6.),
492 ];
493 let g = WeightedAdjacencyList::new_undirected(4, edges);
494 let m = WeightedAdjacencyMatrix::from_adjacency_list(&g);
495 let g1 = WeightedUndirectedAdjacencyMatrixCondensed::from_adjacency_list(&g);
496 let g2 = WeightedUndirectedAdjacencyMatrixCondensed::from_slice(&[1., 2., 3., 4., 5., 6.]);
497 for i in 0..3 {
498 for j in 0..3 {
499 assert_eq!(m[i][j], g1[(i, j)]);
500 assert_eq!(m[i][j], g2[(i, j)]);
501 }
502 }
503 assert_eq!(&g1.edges().collect::<Vec<_>>(), edges);
504 }
505}