Skip to content

Commit 42aadfb

Browse files
committed
Implement scc
1 parent 897c6fd commit 42aadfb

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed

src/internal_scc.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,134 @@
1+
pub struct Csr<E> {
2+
start: Vec<usize>,
3+
elist: Vec<E>,
4+
}
15

6+
impl<E> Csr<E>
7+
where
8+
E: Copy + Clone,
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 labmda 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

Comments
 (0)