Skip to content

Commit 1c8d2ab

Browse files
Merge branch 'master' into feature/maxflow
2 parents 125fc64 + 6d1e6a7 commit 1c8d2ab

File tree

5 files changed

+975
-0
lines changed

5 files changed

+975
-0
lines changed

src/internal_bit.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,30 @@
1+
// Skipped:
2+
//
3+
// - `bsf` = `__builtin_ctz`: is equivalent to `{integer}::trailing_zeros`
14

5+
#[allow(dead_code)]
6+
pub(crate) fn ceil_pow2(n: u32) -> u32 {
7+
32 - n.saturating_sub(1).leading_zeros()
8+
}
9+
10+
#[cfg(test)]
11+
mod tests {
12+
#[test]
13+
fn ceil_pow2() {
14+
// https://github.com/atcoder/ac-library/blob/2088c8e2431c3f4d29a2cfabc6529fe0a0586c48/test/unittest/bit_test.cpp
15+
assert_eq!(0, super::ceil_pow2(0));
16+
assert_eq!(0, super::ceil_pow2(1));
17+
assert_eq!(1, super::ceil_pow2(2));
18+
assert_eq!(2, super::ceil_pow2(3));
19+
assert_eq!(2, super::ceil_pow2(4));
20+
assert_eq!(3, super::ceil_pow2(5));
21+
assert_eq!(3, super::ceil_pow2(6));
22+
assert_eq!(3, super::ceil_pow2(7));
23+
assert_eq!(3, super::ceil_pow2(8));
24+
assert_eq!(4, super::ceil_pow2(9));
25+
assert_eq!(30, super::ceil_pow2(1 << 30));
26+
assert_eq!(31, super::ceil_pow2((1 << 30) + 1));
27+
28+
assert_eq!(32, super::ceil_pow2(u32::max_value()));
29+
}
30+
}

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,
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+
}

src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ pub use fenwicktree::FenwickTree;
2323
pub use math::{crt, floor_sum, inv_mod, pow_mod};
2424
pub use maxflow::{Edge, MfGraph};
2525
pub use mincostflow::MinCostFlowGraph;
26+
pub use modint::{
27+
Barrett, DefaultId, DynamicModInt, Id, Mod1000000007, Mod998244353, ModInt, ModInt1000000007,
28+
ModInt998244353, Modulus, RemEuclidU32, StaticModInt,
29+
};
30+
pub use scc::SccGraph;
2631
pub use string::{
2732
lcp_array, lcp_array_arbitrary, suffix_array, suffix_array_arbitrary, suffix_array_manual,
2833
z_algorithm, z_algorithm_arbitrary,

0 commit comments

Comments
 (0)