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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/unittest.yml +16 -3
  3. data/.rubocop.yml +61 -45
  4. data/README.ja.md +36 -8
  5. data/README.md +7 -4
  6. data/Rakefile +7 -3
  7. data/ac-library-rb.gemspec +11 -4
  8. data/ac-library-rb_header.jpg +0 -0
  9. data/bin/console +1 -1
  10. data/document_en/dsu.md +1 -1
  11. data/document_en/fenwick_tree.md +2 -2
  12. data/document_en/lazy_segtree.md +4 -4
  13. data/document_en/math.md +3 -3
  14. data/document_en/max_flow.md +3 -3
  15. data/document_en/min_cost_flow.md +4 -4
  16. data/document_en/modint.md +4 -4
  17. data/document_en/scc.md +67 -0
  18. data/document_en/segtree.md +2 -2
  19. data/document_ja/dsu.md +1 -1
  20. data/document_ja/fenwick_tree.md +2 -2
  21. data/document_ja/lazy_segtree.md +2 -2
  22. data/document_ja/math.md +3 -3
  23. data/document_ja/max_flow.md +4 -7
  24. data/document_ja/min_cost_flow.md +5 -4
  25. data/document_ja/modint.md +4 -4
  26. data/document_ja/scc.md +9 -8
  27. data/document_ja/segtree.md +2 -2
  28. data/lib/ac-library-rb/version.rb +1 -1
  29. data/lib/convolution.rb +1 -1
  30. data/lib/dsu.rb +14 -1
  31. data/lib/fenwick_tree.rb +4 -0
  32. data/lib/lazy_segtree.rb +2 -6
  33. data/lib/max_flow.rb +27 -26
  34. data/lib/modint.rb +4 -4
  35. data/lib/priority_queue.rb +14 -0
  36. data/lib/scc.rb +43 -41
  37. data/lib/two_sat.rb +1 -1
  38. data/lib_lock/ac-library-rb/convolution.rb +1 -1
  39. data/lib_lock/ac-library-rb/dsu.rb +14 -1
  40. data/lib_lock/ac-library-rb/fenwick_tree.rb +4 -0
  41. data/lib_lock/ac-library-rb/lazy_segtree.rb +2 -6
  42. data/lib_lock/ac-library-rb/max_flow.rb +27 -26
  43. data/lib_lock/ac-library-rb/modint.rb +4 -4
  44. data/lib_lock/ac-library-rb/priority_queue.rb +14 -0
  45. data/lib_lock/ac-library-rb/scc.rb +43 -41
  46. data/lib_lock/ac-library-rb/two_sat.rb +1 -1
  47. metadata +39 -7
@@ -37,39 +37,40 @@ module AcLibraryRb
37
37
 
38
38
  # return edge = [from, to, cap, flow]
39
39
  def [](i)
40
- _e = @g[@pos[i][0]][@pos[i][1]]
41
- _re = @g[_e[0]][_e[1]]
42
- [@pos[i][0], _e[0], _e[-1] + _re[-1], _re[-1]]
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, id)|
49
- _e = @g[from][id]
50
- _re = @g[_e[0]][_e[1]]
51
- [from, _e[0], _e[-1] + _re[-1], _re[-1]]
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
- _e = @g[@pos[i][0]][@pos[i][1]]
57
- _re = @g[_e[0]][_e[1]]
58
- _e[2] = new_cap - new_flow
59
- _re[2] = new_flow
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, level, que)
70
+ level = bfs(s, t)
70
71
  break if level[t] == -1
71
72
 
72
- iter.fill(0)
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, level, que)
103
- level.fill(-1)
103
+ def bfs(s, t)
104
+ level = Array.new(@n, -1)
104
105
  level[s] = 0
105
- que.clear
106
- que << s
106
+ que = [s]
107
107
 
108
108
  while (v = que.shift)
109
- @g[v].each do |e|
110
- next if e[2] == 0 || level[e[0]] >= 0
109
+ @g[v].each do |u, _, cap|
110
+ next if cap == 0 || level[u] >= 0
111
111
 
112
- level[e[0]] = level[v] + 1
113
- return nil if e[0] == t
112
+ level[u] = level[v] + 1
113
+ return level if u == t
114
114
 
115
- que << e[0]
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? Integer and 1 <= mod
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 or n == 7 or n == 61
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 and y != 1 and y != 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 and (t & 1) == 0
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 and 0 <= to && to < @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 << [from, to]
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
- start, elist = csr
44
- now_ord = group_num = 0
45
- visited, low, ord, ids = [], [], [-1] * @n, []
46
- dfs = ->(v) {
47
- low[v] = ord[v] = now_ord
48
- now_ord += 1
49
- visited << v
50
- (start[v]...start[v + 1]).each do |i|
51
- to = elist[i]
52
- low[v] = if ord[to] == -1
53
- dfs.(to)
54
- [low[v], low[to]].min
55
- else
56
- [low[v], ord[to]].min
57
- end
58
- end
59
- if low[v] == ord[v]
60
- loop do
61
- u = visited.pop
62
- ord[u] = @n
63
- ids[u] = group_num
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
- def csr
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
- [start, elist]
84
+
85
+ ord.map! { |e| group_num - e - 1 }
86
+ [group_num, ord]
85
87
  end
86
88
  end
87
89
  end
@@ -13,7 +13,7 @@ module AcLibraryRb
13
13
  attr_reader :answer
14
14
 
15
15
  def add_clause(i, f, j, g)
16
- unless 0 <= i && i < @n and 0 <= j && j < @n
16
+ unless 0 <= i && i < @n && 0 <= j && j < @n
17
17
  raise ArgumentError.new("i:#{i} and j:#{j} must be in (0...#{@n})")
18
18
  end
19
19
 
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.6.1
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: 2021-08-09 00:00:00.000000000 Z
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
- description: |-
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, suffix_array, lcp_array, z_algorithm, crt, inv_mod, floor_sum, max_flow, min_cost_flow......
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.5.0
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.2.22
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).