|
| 1 | +pub struct Csr<E> { |
| 2 | + start: Vec<usize>, |
| 3 | + elist: Vec<E>, |
| 4 | +} |
1 | 5 |
|
| 6 | +impl<E> Csr<E> |
| 7 | +where |
| 8 | + E: Copy, |
| 9 | +{ |
| 10 | + pub fn new(n: usize, edges: &[(usize, E)], init: E) -> Self { |
| 11 | + let mut csr = Csr { |
| 12 | + start: vec![0; n + 1], |
| 13 | + elist: vec![init; edges.len()], |
| 14 | + }; |
| 15 | + for e in edges.iter() { |
| 16 | + csr.start[e.0 + 1] += 1; |
| 17 | + } |
| 18 | + for i in 1..=n { |
| 19 | + csr.start[i] += csr.start[i - 1]; |
| 20 | + } |
| 21 | + let mut counter = csr.start.clone(); |
| 22 | + for e in edges.iter() { |
| 23 | + csr.elist[counter[e.0]] = e.1; |
| 24 | + counter[e.0] += 1; |
| 25 | + } |
| 26 | + csr |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +#[derive(Copy, Clone)] |
| 31 | +struct _Edge { |
| 32 | + to: usize, |
| 33 | +} |
| 34 | + |
| 35 | +/// Reference: |
| 36 | +/// R. Tarjan, |
| 37 | +/// Depth-First Search and Linear Graph Algorithms |
| 38 | +pub struct SccGraph { |
| 39 | + n: usize, |
| 40 | + edges: Vec<(usize, _Edge)>, |
| 41 | +} |
| 42 | + |
| 43 | +impl SccGraph { |
| 44 | + pub fn new(n: usize) -> Self { |
| 45 | + SccGraph { n, edges: vec![] } |
| 46 | + } |
| 47 | + |
| 48 | + pub fn num_vertices(&self) -> usize { |
| 49 | + self.n |
| 50 | + } |
| 51 | + |
| 52 | + pub fn add_edge(&mut self, from: usize, to: usize) { |
| 53 | + self.edges.push((from, _Edge { to })); |
| 54 | + } |
| 55 | + |
| 56 | + /// return pair of (# of scc, scc id) |
| 57 | + pub fn scc_ids(&self) -> (usize, Vec<usize>) { |
| 58 | + // In C++ ac-library, this function is implemented by using recursive lambda functions. |
| 59 | + // Instead, we use fn and struct for capturing environments. |
| 60 | + struct _Env { |
| 61 | + g: Csr<_Edge>, |
| 62 | + now_ord: usize, |
| 63 | + group_num: usize, |
| 64 | + visited: Vec<usize>, |
| 65 | + low: Vec<usize>, |
| 66 | + ord: Vec<Option<usize>>, |
| 67 | + ids: Vec<usize>, |
| 68 | + } |
| 69 | + let mut env = _Env { |
| 70 | + g: Csr::new(self.n, &self.edges, _Edge { to: 0 }), |
| 71 | + now_ord: 0, |
| 72 | + group_num: 0, |
| 73 | + visited: Vec::with_capacity(self.n), |
| 74 | + low: vec![0; self.n], |
| 75 | + ord: vec![None; self.n], |
| 76 | + ids: vec![0; self.n], |
| 77 | + }; |
| 78 | + |
| 79 | + fn dfs(v: usize, n: usize, env: &mut _Env) { |
| 80 | + env.low[v] = env.now_ord; |
| 81 | + env.ord[v] = Some(env.now_ord); |
| 82 | + env.now_ord += 1; |
| 83 | + env.visited.push(v); |
| 84 | + |
| 85 | + for i in env.g.start[v]..env.g.start[v + 1] { |
| 86 | + let to = env.g.elist[i].to; |
| 87 | + if let Some(x) = env.ord[to] { |
| 88 | + env.low[v] = std::cmp::min(env.low[v], x); |
| 89 | + } else { |
| 90 | + dfs(to, n, env); |
| 91 | + env.low[v] = std::cmp::min(env.low[v], env.low[to]); |
| 92 | + } |
| 93 | + } |
| 94 | + if env.low[v] == env.ord[v].unwrap() { |
| 95 | + loop { |
| 96 | + let u = *env.visited.last().unwrap(); |
| 97 | + env.visited.pop(); |
| 98 | + env.ord[u] = Some(n); |
| 99 | + env.ids[u] = env.group_num; |
| 100 | + if u == v { |
| 101 | + break; |
| 102 | + } |
| 103 | + } |
| 104 | + env.group_num += 1; |
| 105 | + } |
| 106 | + } |
| 107 | + for i in 0..self.n { |
| 108 | + if env.ord[i].is_none() { |
| 109 | + dfs(i, self.n, &mut env); |
| 110 | + } |
| 111 | + } |
| 112 | + for x in env.ids.iter_mut() { |
| 113 | + *x = env.group_num - 1 - *x; |
| 114 | + } |
| 115 | + (env.group_num, env.ids) |
| 116 | + } |
| 117 | + |
| 118 | + pub fn scc(&self) -> Vec<Vec<usize>> { |
| 119 | + let ids = self.scc_ids(); |
| 120 | + let group_num = ids.0; |
| 121 | + let mut counts = vec![0usize; group_num]; |
| 122 | + for &x in ids.1.iter() { |
| 123 | + counts[x] += 1; |
| 124 | + } |
| 125 | + let mut groups: Vec<Vec<usize>> = (0..ids.0).map(|_| vec![]).collect(); |
| 126 | + for i in 0..group_num { |
| 127 | + groups[i].reserve(counts[i]); |
| 128 | + } |
| 129 | + for i in 0..self.n { |
| 130 | + groups[ids.1[i]].push(i); |
| 131 | + } |
| 132 | + groups |
| 133 | + } |
| 134 | +} |
0 commit comments