ac-library-rb 0.6.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/unittest.yml +16 -3
- data/.rubocop.yml +61 -45
- data/README.ja.md +36 -8
- data/README.md +7 -4
- data/Rakefile +7 -3
- data/ac-library-rb.gemspec +11 -4
- data/ac-library-rb_header.jpg +0 -0
- data/bin/console +1 -1
- data/document_en/dsu.md +1 -1
- data/document_en/fenwick_tree.md +2 -2
- data/document_en/lazy_segtree.md +4 -4
- data/document_en/math.md +3 -3
- data/document_en/max_flow.md +3 -3
- data/document_en/min_cost_flow.md +4 -4
- data/document_en/modint.md +4 -4
- data/document_en/scc.md +67 -0
- data/document_en/segtree.md +2 -2
- data/document_ja/dsu.md +1 -1
- data/document_ja/fenwick_tree.md +2 -2
- data/document_ja/lazy_segtree.md +2 -2
- data/document_ja/math.md +3 -3
- data/document_ja/max_flow.md +4 -7
- data/document_ja/min_cost_flow.md +5 -4
- data/document_ja/modint.md +4 -4
- data/document_ja/scc.md +9 -8
- data/document_ja/segtree.md +2 -2
- data/lib/ac-library-rb/version.rb +1 -1
- data/lib/convolution.rb +1 -1
- data/lib/dsu.rb +14 -1
- data/lib/fenwick_tree.rb +4 -0
- data/lib/lazy_segtree.rb +2 -6
- data/lib/max_flow.rb +27 -26
- data/lib/modint.rb +4 -4
- data/lib/priority_queue.rb +14 -0
- data/lib/scc.rb +43 -41
- data/lib/two_sat.rb +1 -1
- data/lib_lock/ac-library-rb/convolution.rb +1 -1
- data/lib_lock/ac-library-rb/dsu.rb +14 -1
- data/lib_lock/ac-library-rb/fenwick_tree.rb +4 -0
- data/lib_lock/ac-library-rb/lazy_segtree.rb +2 -6
- data/lib_lock/ac-library-rb/max_flow.rb +27 -26
- data/lib_lock/ac-library-rb/modint.rb +4 -4
- data/lib_lock/ac-library-rb/priority_queue.rb +14 -0
- data/lib_lock/ac-library-rb/scc.rb +43 -41
- data/lib_lock/ac-library-rb/two_sat.rb +1 -1
- metadata +39 -7
@@ -37,39 +37,40 @@ module AcLibraryRb
|
|
37
37
|
|
38
38
|
# return edge = [from, to, cap, flow]
|
39
39
|
def [](i)
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
from, from_id = @pos[i]
|
41
|
+
|
42
|
+
to, to_id, cap = @g[from][from_id] # edge
|
43
|
+
_from, _from_id, flow = @g[to][to_id] # reverse edge
|
44
|
+
|
45
|
+
[from, to, cap + flow, flow]
|
43
46
|
end
|
44
47
|
alias get_edge []
|
45
48
|
alias edge []
|
46
49
|
|
47
50
|
def edges
|
48
|
-
@pos.map do |(from,
|
49
|
-
|
50
|
-
|
51
|
-
[from,
|
51
|
+
@pos.map do |(from, from_id)|
|
52
|
+
to, to_id, cap = @g[from][from_id]
|
53
|
+
_from, _from_id, flow = @g[to][to_id]
|
54
|
+
[from, to, cap + flow, flow]
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
55
58
|
def change_edge(i, new_cap, new_flow)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
59
|
+
from, from_id = @pos[i]
|
60
|
+
|
61
|
+
e = @g[from][from_id]
|
62
|
+
re = @g[e[0]][e[1]]
|
63
|
+
e[2] = new_cap - new_flow
|
64
|
+
re[2] = new_flow
|
60
65
|
end
|
61
66
|
|
62
67
|
def flow(s, t, flow_limit = 1 << 64)
|
63
|
-
level = Array.new(@n)
|
64
|
-
iter = Array.new(@n)
|
65
|
-
que = []
|
66
|
-
|
67
68
|
flow = 0
|
68
69
|
while flow < flow_limit
|
69
|
-
bfs(s, t
|
70
|
+
level = bfs(s, t)
|
70
71
|
break if level[t] == -1
|
71
72
|
|
72
|
-
iter
|
73
|
+
iter = [0] * @n
|
73
74
|
while flow < flow_limit
|
74
75
|
f = dfs(t, flow_limit - flow, s, level, iter)
|
75
76
|
break if f == 0
|
@@ -99,22 +100,22 @@ module AcLibraryRb
|
|
99
100
|
|
100
101
|
private
|
101
102
|
|
102
|
-
def bfs(s, t
|
103
|
-
level.
|
103
|
+
def bfs(s, t)
|
104
|
+
level = Array.new(@n, -1)
|
104
105
|
level[s] = 0
|
105
|
-
que
|
106
|
-
que << s
|
106
|
+
que = [s]
|
107
107
|
|
108
108
|
while (v = que.shift)
|
109
|
-
@g[v].each do |
|
110
|
-
next if
|
109
|
+
@g[v].each do |u, _, cap|
|
110
|
+
next if cap == 0 || level[u] >= 0
|
111
111
|
|
112
|
-
level[
|
113
|
-
return
|
112
|
+
level[u] = level[v] + 1
|
113
|
+
return level if u == t
|
114
114
|
|
115
|
-
que <<
|
115
|
+
que << u
|
116
116
|
end
|
117
117
|
end
|
118
|
+
level
|
118
119
|
end
|
119
120
|
|
120
121
|
def dfs(v, up, s, level, iter)
|
@@ -5,7 +5,7 @@ module AcLibraryRb
|
|
5
5
|
class ModInt < Numeric
|
6
6
|
class << self
|
7
7
|
def set_mod(mod)
|
8
|
-
raise ArgumentError unless mod.is_a?
|
8
|
+
raise ArgumentError unless mod.is_a?(Integer) && (1 <= mod)
|
9
9
|
|
10
10
|
$_mod = mod
|
11
11
|
$_mod_is_prime = ModInt.prime?(mod)
|
@@ -27,7 +27,7 @@ module AcLibraryRb
|
|
27
27
|
|
28
28
|
def prime?(n)
|
29
29
|
return false if n <= 1
|
30
|
-
return true if n == 2
|
30
|
+
return true if (n == 2) || (n == 7) || (n == 61)
|
31
31
|
return false if (n & 1) == 0
|
32
32
|
|
33
33
|
d = n - 1
|
@@ -35,11 +35,11 @@ module AcLibraryRb
|
|
35
35
|
[2, 7, 61].each do |a|
|
36
36
|
t = d
|
37
37
|
y = a.pow(t, n)
|
38
|
-
while t != n - 1
|
38
|
+
while (t != n - 1) && (y != 1) && (y != n - 1)
|
39
39
|
y = y * y % n
|
40
40
|
t <<= 1
|
41
41
|
end
|
42
|
-
return false if y != n - 1
|
42
|
+
return false if (y != n - 1) && ((t & 1) == 0)
|
43
43
|
end
|
44
44
|
true
|
45
45
|
end
|
@@ -14,11 +14,17 @@ module AcLibraryRb
|
|
14
14
|
heapify
|
15
15
|
end
|
16
16
|
|
17
|
+
def self.[](*array, &comp)
|
18
|
+
new(array, &comp)
|
19
|
+
end
|
20
|
+
|
17
21
|
attr_reader :heap
|
22
|
+
alias to_a heap
|
18
23
|
|
19
24
|
# Push new element to the heap.
|
20
25
|
def push(item)
|
21
26
|
shift_down(0, @heap.push(item).size - 1)
|
27
|
+
self
|
22
28
|
end
|
23
29
|
|
24
30
|
alias << push
|
@@ -47,6 +53,14 @@ module AcLibraryRb
|
|
47
53
|
@heap.empty?
|
48
54
|
end
|
49
55
|
|
56
|
+
def size
|
57
|
+
@heap.size
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
"<#{self.class}: @heap:(#{heap.join(', ')}), @comp:<#{@comp.class} #{@comp.source_location.join(':')}>>"
|
62
|
+
end
|
63
|
+
|
50
64
|
private
|
51
65
|
|
52
66
|
def heapify
|
@@ -4,17 +4,17 @@ module AcLibraryRb
|
|
4
4
|
# initialize graph with n vertices
|
5
5
|
def initialize(n)
|
6
6
|
@n = n
|
7
|
-
@edges = []
|
7
|
+
@edges = Array.new(n) { [] }
|
8
8
|
end
|
9
9
|
|
10
10
|
# add directed edge
|
11
11
|
def add_edge(from, to)
|
12
|
-
unless 0 <= from && from < @n
|
12
|
+
unless 0 <= from && from < @n && 0 <= to && to < @n
|
13
13
|
msg = "Wrong params: from=#{from} and to=#{to} must be in 0...#{@n}"
|
14
14
|
raise ArgumentError.new(msg)
|
15
15
|
end
|
16
16
|
|
17
|
-
@edges <<
|
17
|
+
@edges[from] << to
|
18
18
|
self
|
19
19
|
end
|
20
20
|
|
@@ -29,7 +29,7 @@ module AcLibraryRb
|
|
29
29
|
|
30
30
|
# returns list of strongly connected components
|
31
31
|
# the components are sorted in topological order
|
32
|
-
# O(@n + @edges.size)
|
32
|
+
# O(@n + @edges.sum(&:size))
|
33
33
|
def scc
|
34
34
|
group_num, ids = scc_ids
|
35
35
|
groups = Array.new(group_num) { [] }
|
@@ -40,48 +40,50 @@ module AcLibraryRb
|
|
40
40
|
private
|
41
41
|
|
42
42
|
def scc_ids
|
43
|
-
|
44
|
-
|
45
|
-
visited
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
43
|
+
now_ord = 0
|
44
|
+
|
45
|
+
visited = []
|
46
|
+
low = Array.new(@n, 1 << 60)
|
47
|
+
ord = Array.new(@n, -1)
|
48
|
+
group_num = 0
|
49
|
+
|
50
|
+
(0...@n).each do |v|
|
51
|
+
next if ord[v] != -1
|
52
|
+
|
53
|
+
stack = [[v, 0]]
|
54
|
+
|
55
|
+
while (v, i = stack.pop)
|
56
|
+
if i == 0
|
57
|
+
visited << v
|
58
|
+
low[v] = ord[v] = now_ord
|
59
|
+
now_ord += 1
|
60
|
+
end
|
61
|
+
|
62
|
+
while i < @edges[v].size
|
63
|
+
u = @edges[v][i]
|
64
|
+
i += 1
|
65
|
+
|
66
|
+
if ord[u] == -1
|
67
|
+
stack << [v, i] << [u, 0]
|
68
|
+
break 1
|
69
|
+
end
|
70
|
+
end and next
|
71
|
+
|
72
|
+
low[v] = [low[v], @edges[v].map { |e| low[e] }.min || @n].min
|
73
|
+
next if low[v] != ord[v]
|
74
|
+
|
75
|
+
while (u = visited.pop)
|
76
|
+
low[u] = @n
|
77
|
+
ord[u] = group_num
|
64
78
|
break if u == v
|
65
79
|
end
|
66
80
|
group_num += 1
|
67
|
-
end
|
68
|
-
}
|
69
|
-
@n.times { |i| dfs.(i) if ord[i] == -1 }
|
70
|
-
ids = ids.map { |x| group_num - 1 - x }
|
71
|
-
[group_num, ids]
|
72
|
-
end
|
73
81
|
|
74
|
-
|
75
|
-
start = [0] * (@n + 1)
|
76
|
-
elist = [nil] * @edges.size
|
77
|
-
@edges.each { |(i, _)| start[i + 1] += 1 }
|
78
|
-
@n.times { |i| start[i + 1] += start[i] }
|
79
|
-
counter = start.dup
|
80
|
-
@edges.each do |(i, j)|
|
81
|
-
elist[counter[i]] = j
|
82
|
-
counter[i] += 1
|
82
|
+
end
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
|
+
ord.map! { |e| group_num - e - 1 }
|
86
|
+
[group_num, ord]
|
85
87
|
end
|
86
88
|
end
|
87
89
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ac-library-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- universato
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: prime
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: minitest
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,9 +66,24 @@ dependencies:
|
|
52
66
|
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
55
|
-
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov-cobertura
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: |
|
56
84
|
ac-library-rb is a ruby port of AtCoder Library (ACL).
|
57
|
-
DSU(UnionFind), FenwickTree, PriorityQueue, Segtree, SCC, 2-SAT,
|
85
|
+
DSU(UnionFind), FenwickTree, PriorityQueue, Segtree, SCC, 2-SAT,
|
86
|
+
suffix_array, lcp_array, z_algorithm, crt, inv_mod, floor_sum, max_flow, min_cost_flow......
|
58
87
|
email:
|
59
88
|
- universato@gmail.com
|
60
89
|
executables: []
|
@@ -70,6 +99,7 @@ files:
|
|
70
99
|
- README.md
|
71
100
|
- Rakefile
|
72
101
|
- ac-library-rb.gemspec
|
102
|
+
- ac-library-rb_header.jpg
|
73
103
|
- bin/console
|
74
104
|
- bin/lock_lib.rb
|
75
105
|
- bin/setup
|
@@ -84,6 +114,7 @@ files:
|
|
84
114
|
- document_en/min_cost_flow.md
|
85
115
|
- document_en/modint.md
|
86
116
|
- document_en/priority_queue.md
|
117
|
+
- document_en/scc.md
|
87
118
|
- document_en/segtree.md
|
88
119
|
- document_en/string.md
|
89
120
|
- document_en/two_sat.md
|
@@ -151,23 +182,24 @@ licenses:
|
|
151
182
|
metadata:
|
152
183
|
homepage_uri: https://github.com/universato/ac-library-rb
|
153
184
|
source_code_uri: https://github.com/universato/ac-library-rb
|
185
|
+
rubygems_mfa_required: 'true'
|
154
186
|
post_install_message:
|
155
187
|
rdoc_options: []
|
156
188
|
require_paths:
|
157
189
|
- lib_lock
|
158
|
-
- lib_helpers
|
190
|
+
- lib_helpers"
|
159
191
|
required_ruby_version: !ruby/object:Gem::Requirement
|
160
192
|
requirements:
|
161
193
|
- - ">="
|
162
194
|
- !ruby/object:Gem::Version
|
163
|
-
version: 2.
|
195
|
+
version: 2.7.0
|
164
196
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
197
|
requirements:
|
166
198
|
- - ">="
|
167
199
|
- !ruby/object:Gem::Version
|
168
200
|
version: '0'
|
169
201
|
requirements: []
|
170
|
-
rubygems_version: 3.
|
202
|
+
rubygems_version: 3.3.3
|
171
203
|
signing_key:
|
172
204
|
specification_version: 4
|
173
205
|
summary: ac-library-rb is a ruby port of AtCoder Library (ACL).
|