Skip to content

Commit 2843c8e

Browse files
committed
Merge remote-tracking branch 'upstream/master' into modint
2 parents 59b551f + 897c6fd commit 2843c8e

File tree

3 files changed

+482
-0
lines changed

3 files changed

+482
-0
lines changed

src/dsu.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,89 @@
1+
/// Implement (union by size) + (path compression)
2+
/// Reference:
3+
/// Zvi Galil and Giuseppe F. Italiano,
4+
/// Data structures and algorithms for disjoint set union problems
5+
pub struct Dsu {
6+
n: usize,
7+
// root node: -1 * component size
8+
// otherwise: parent
9+
parent_or_size: Vec<i32>,
10+
}
111

12+
impl Dsu {
13+
// 0 <= size <= 10^8 is constrained.
14+
pub fn new(size: usize) -> Self {
15+
Self {
16+
n: size,
17+
parent_or_size: vec![-1; size],
18+
}
19+
}
20+
pub fn merge(&mut self, a: usize, b: usize) -> usize {
21+
assert!(a < self.n);
22+
assert!(b < self.n);
23+
let (mut x, mut y) = (self.leader(a), self.leader(b));
24+
if x == y {
25+
return x;
26+
}
27+
if -self.parent_or_size[x] < -self.parent_or_size[y] {
28+
std::mem::swap(&mut x, &mut y);
29+
}
30+
self.parent_or_size[x] += self.parent_or_size[y];
31+
self.parent_or_size[y] = x as i32;
32+
x
33+
}
34+
35+
pub fn same(&mut self, a: usize, b: usize) -> bool {
36+
assert!(a < self.n);
37+
assert!(b < self.n);
38+
self.leader(a) == self.leader(b)
39+
}
40+
pub fn leader(&mut self, a: usize) -> usize {
41+
assert!(a < self.n);
42+
if self.parent_or_size[a] < 0 {
43+
return a;
44+
}
45+
self.parent_or_size[a] = self.leader(self.parent_or_size[a] as usize) as i32;
46+
self.parent_or_size[a] as usize
47+
}
48+
pub fn size(&mut self, a: usize) -> usize {
49+
assert!(a < self.n);
50+
let x = self.leader(a);
51+
-self.parent_or_size[x] as usize
52+
}
53+
pub fn groups(&mut self) -> Vec<Vec<usize>> {
54+
let mut leader_buf = vec![0; self.n];
55+
let mut group_size = vec![0; self.n];
56+
for i in 0..self.n {
57+
leader_buf[i] = self.leader(i);
58+
group_size[leader_buf[i]] += 1;
59+
}
60+
let mut result = vec![Vec::new(); self.n];
61+
for i in 0..self.n {
62+
result[i].reserve(group_size[i]);
63+
}
64+
for i in 0..self.n {
65+
result[leader_buf[i]].push(i);
66+
}
67+
result
68+
.into_iter()
69+
.filter(|x| !x.is_empty())
70+
.collect::<Vec<Vec<usize>>>()
71+
}
72+
}
73+
74+
#[cfg(test)]
75+
mod tests {
76+
use super::*;
77+
78+
#[test]
79+
fn dsu_works() {
80+
let mut d = Dsu::new(4);
81+
d.merge(0, 1);
82+
assert_eq!(d.same(0, 1), true);
83+
d.merge(1, 2);
84+
assert_eq!(d.same(0, 2), true);
85+
assert_eq!(d.size(0), 3);
86+
assert_eq!(d.same(0, 3), false);
87+
assert_eq!(d.groups(), vec![vec![0, 1, 2], vec![3]]);
88+
}
89+
}

src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod mincostflow;
88
mod modint;
99
mod scc;
1010
mod segtree;
11+
#[allow(clippy::many_single_char_names)]
1112
mod string;
1213
mod twosat;
1314

@@ -17,8 +18,13 @@ pub(crate) mod internal_queue;
1718
pub(crate) mod internal_scc;
1819
pub(crate) mod internal_type_traits;
1920

21+
pub use dsu::Dsu;
2022
pub use fenwicktree::FenwickTree;
2123
pub use modint::{
2224
Barrett, DefaultId, DynamicModInt, Id, Mod1000000007, Mod998244353, ModInt, ModInt1000000007,
2325
ModInt998244353, Modulus, RemEuclidU32, StaticModInt,
2426
};
27+
pub use string::{
28+
lcp_array, lcp_array_arbitrary, suffix_array, suffix_array_arbitrary, suffix_array_manual,
29+
z_algorithm, z_algorithm_arbitrary,
30+
};

0 commit comments

Comments
 (0)