1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
use std::collections::HashSet; #[derive(Debug, Eq, PartialEq)] struct Node { id: usize, discovery: usize, lowest: usize, on_stack: bool, } impl Node { pub fn new(id: usize) -> Self { let discovery = std::usize::MAX; let lowest = std::usize::MAX; let on_stack = false; Node { id, discovery, lowest, on_stack, } } fn visit(&mut self, time: usize) { self.discovery = time; } fn is_visited(&self) -> bool { self.discovery != std::usize::MAX } } #[derive(Debug, Eq, PartialEq)] pub enum EdgeKind { TreeEdge, BackEdge, CrossEdge, ForwardEdge, } #[derive(Debug, Eq, PartialEq)] pub struct Edge { pub tail: usize, pub head: usize, pub kind: EdgeKind, } impl Edge { fn new(tail: usize, head: usize, kind: EdgeKind) -> Self { Edge { tail, head, kind } } } #[derive(Debug, Eq, PartialEq)] pub struct Graph { pub n: usize, pub edges: Vec<Edge>, adj: Vec<HashSet<usize>>, nodes: Vec<Node>, stack: Vec<usize>, time: usize, } impl Graph { pub fn new(n: usize) -> Self { let time = 0; let adj = vec![HashSet::new(); n]; let nodes = (0..n).map(Node::new).collect(); let edges = vec![]; let stack = vec![]; Graph { n, time, adj, nodes, edges, stack, } } pub fn init_with_edges(&mut self, edges: Vec<Vec<i32>>, directed: bool) { for edge in edges { let u = edge[0] as usize; let v = edge[1] as usize; if !directed { self.adj[u].insert(v); self.adj[v].insert(u); } else { self.adj[u].insert(v); } } } pub fn dfs(&mut self, u: usize, parent: usize) { self.nodes[u].visit(self.time); self.time += 1; let neighbours: Vec<usize> = self.adj[u].iter().copied().collect(); for v in neighbours { if v == parent { continue; } if !self.nodes[v].is_visited() { self.edges.push(Edge::new(u, v, EdgeKind::TreeEdge)); self.dfs(v, u); } else { self.edges.push(Edge::new(u, v, EdgeKind::BackEdge)); } } } pub fn travase(&mut self) { for u in 0..self.n { if !self.nodes[u].is_visited() { self.dfs(u, u); } } } }