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
data/document_en/segtree.md
CHANGED
@@ -147,10 +147,10 @@ It returns an index l that satisfies both of the following.
|
|
147
147
|
|
148
148
|
## Verified
|
149
149
|
|
150
|
-
- [ALPC: J
|
150
|
+
- [ALPC: J - Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_j)
|
151
151
|
- [AC Code(884ms) max_right](https://atcoder.jp/contests/practice2/submissions/23196480)
|
152
152
|
- [AC Code(914ms) min_left](https://atcoder.jp/contests/practice2/submissions/23197311)
|
153
|
-
- [F
|
153
|
+
- [F - Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
|
154
154
|
- [AC Code(1538ms)](https://atcoder.jp/contests/abc185/submissions/18746817): Segtree(xor)
|
155
155
|
- [AC Code(821ms)](https://atcoder.jp/contests/abc185/submissions/18769200): FenwickTree(BIT) xor
|
156
156
|
|
data/document_ja/dsu.md
CHANGED
data/document_ja/fenwick_tree.md
CHANGED
@@ -69,9 +69,9 @@ fw._sum(pos)
|
|
69
69
|
|
70
70
|
## Verified
|
71
71
|
|
72
|
-
- [AtCoder ALPC B
|
72
|
+
- [AtCoder ALPC B - Fenwick Tree](https://atcoder.jp/contests/practice2/tasks/practice2_b)
|
73
73
|
[ACコード(17074108)]https://atcoder.jp/contests/practice2/submissions/17074108 (1272ms)
|
74
|
-
- [F
|
74
|
+
- [F - Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
|
75
75
|
FenwickTree(BIT)をxorに改造するだけでも解けます。
|
76
76
|
[ACコード(821ms)](https://atcoder.jp/contests/abc185/submissions/18769200)。FenwickTree(BIT)のxor改造版です。
|
77
77
|
|
data/document_ja/lazy_segtree.md
CHANGED
@@ -138,8 +138,8 @@ LazySegtree上で、二分探索をします。
|
|
138
138
|
- [AIZU ONLINE JUDGE DSL\_2\_I RSQ and RUQ](https://onlinejudge.u-aizu.ac.jp/problems/DSL_2_I) ([旧DSL_2_I](http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=DSL_2_I))
|
139
139
|
|
140
140
|
以下の問題は、Rubyでは実行時間が厳しくTLEになりACできてないです。
|
141
|
-
- [ALPC: K
|
142
|
-
- [ALPC: L
|
141
|
+
- [ALPC: K - Range Affine Range Sum](https://atcoder.jp/contests/practice2/tasks/practice2_k)
|
142
|
+
- [ALPC: L - Lazy Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_l)
|
143
143
|
|
144
144
|
下記は、ジャッジにだしてないが、サンプルに正解。`max_right`, `min_left`を使う問題。
|
145
145
|
- [Quora Programming Challenge 2021: Skyscraper](https://jonathanirvin.gs/files/division2_3d16774b0423.pdf#page=5)
|
data/document_ja/math.md
CHANGED
@@ -70,7 +70,7 @@ Chinese remainder theorem
|
|
70
70
|
### Verified
|
71
71
|
|
72
72
|
問題
|
73
|
-
- [No\.187 中華風 \(Hard\)
|
73
|
+
- [No\.187 中華風 \(Hard\) - yukicoder](https://yukicoder.me/problems/no/187)
|
74
74
|
|
75
75
|
## floor_sum(n, m, a, b)
|
76
76
|
|
@@ -86,7 +86,7 @@ $\sum_{i = 0}^{n - 1} \mathrm{floor}(\frac{a \times i + b}{m})$
|
|
86
86
|
|
87
87
|
### Verified
|
88
88
|
|
89
|
-
[ALPC: C
|
89
|
+
[ALPC: C - Floor Sum](https://atcoder.jp/contests/practice2/tasks/practice2_c)
|
90
90
|
- [ACコード 426ms 2020/9/14](https://atcoder.jp/contests/practice2/submissions/16735215)
|
91
91
|
|
92
92
|
## 参考リンク
|
@@ -107,7 +107,7 @@ $\sum_{i = 0}^{n - 1} \mathrm{floor}(\frac{a \times i + b}{m})$
|
|
107
107
|
- [本家ライブラリの実装コード internal_math.hpp](https://github.com/atcoder/ac-library/blob/master/atcoder/internal_math.hpp)
|
108
108
|
- [本家ライブラリのテストコード math_test.cpp](https://github.com/atcoder/ac-library/blob/master/test/unittest/math_test.cpp)
|
109
109
|
- [本家ライブラリのドキュメント math.md](https://github.com/atcoder/ac-library/blob/master/document_ja/math.md)
|
110
|
-
- [Relax the constraints of floor\_sum? · Issue \#33 · atcoder/ac
|
110
|
+
- [Relax the constraints of floor\_sum? · Issue \#33 · atcoder/ac-library](https://github.com/atcoder/ac-library/issues/33)
|
111
111
|
|
112
112
|
## Q&A
|
113
113
|
|
data/document_ja/max_flow.md
CHANGED
@@ -87,9 +87,9 @@ graph.edges
|
|
87
87
|
|
88
88
|
## Verified
|
89
89
|
|
90
|
-
[ALPC: D
|
90
|
+
[ALPC: D - Maxflow](https://atcoder.jp/contests/practice2/tasks/practice2_d)
|
91
91
|
- [ACコード 211ms 2020/9/17](https://atcoder.jp/contests/practice2/submissions/16789801)
|
92
|
-
- [ALPC: D解説
|
92
|
+
- [ALPC: D解説 - Qiita](https://qiita.com/magurofly/items/bfaf6724418bfde86bd0)
|
93
93
|
|
94
94
|
## 参考リンク
|
95
95
|
|
@@ -108,7 +108,7 @@ graph.edges
|
|
108
108
|
|
109
109
|
### `flow`メソッドの`flow_limit`のデフォルトは 何故`1 << 64`
|
110
110
|
|
111
|
-
|
111
|
+
意味はないです。
|
112
112
|
`Float::MAX`や`Float::INFINITY`でも良さそうですが、遅くならないでしょうか。
|
113
113
|
|
114
114
|
### 辺にStructは使わないの
|
@@ -119,10 +119,7 @@ Structを使った方がコードがスリムになって上級者ぽくもあ
|
|
119
119
|
|
120
120
|
### `_`始まりの変数の意図は
|
121
121
|
|
122
|
-
|
123
|
-
|
124
|
-
1. `_e`や`_re`は、本家ACLコードと一緒に読みやすいように、変数名を合わせています。
|
125
|
-
2. `_rev`は、`each`で回す都合上吐き出すけれど使わないので、「使わない」という意図で`_`始まりにしています。
|
122
|
+
`_rev`は、`each`で回す都合上吐き出すけれど使わないので、「使わない」という意図で`_`始まりにしています。
|
126
123
|
|
127
124
|
```ruby
|
128
125
|
@g[q].each do |(to, _rev, cap)|
|
@@ -73,7 +73,7 @@ graph.edges
|
|
73
73
|
|
74
74
|
## Verified
|
75
75
|
|
76
|
-
[ALPC: E
|
76
|
+
[ALPC: E - MinCostFlow](https://atcoder.jp/contests/practice2/tasks/practice2_e)
|
77
77
|
- [1213ms 2020/9/17](https://atcoder.jp/contests/practice2/submissions/16792967)
|
78
78
|
|
79
79
|
## 参考リンク
|
@@ -86,17 +86,18 @@ graph.edges
|
|
86
86
|
- [本家ライブラリの実装コード mincostflow.hpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/atcoder/mincostflow.hpp)
|
87
87
|
- [本家ライブラリのテストコード mincostflow_test.cpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/test/unittest/mincostflow_test.cpp)
|
88
88
|
|
89
|
-
##
|
89
|
+
## 備考
|
90
90
|
|
91
91
|
### エイリアスの意図は
|
92
92
|
|
93
|
-
|
93
|
+
本家ライブラリの最小費用流の方のメソッド名が長いので、エイリアスを持たせています。
|
94
|
+
本家ライブラリの最大流の方のメソッド名は短いので、不思議です。
|
94
95
|
|
95
96
|
### `Float::INFINITY`ではなく、`Float::MAX`を使う意図とは
|
96
97
|
|
97
98
|
特に検証してないので、何の数値がいいのか検証したいです。
|
98
99
|
|
99
|
-
`Integer
|
100
|
+
`Integer`クラスでも良いような気がしました。
|
100
101
|
|
101
102
|
### 辺にStructは使わないの
|
102
103
|
|
data/document_ja/modint.md
CHANGED
@@ -199,9 +199,9 @@ p 12.to_m == 1 #=> true
|
|
199
199
|
|
200
200
|
## Verified
|
201
201
|
|
202
|
-
- [ABC156: D
|
202
|
+
- [ABC156: D - Bouquet](https://atcoder.jp/contests/abc156/tasks/abc156_d) 2020/2/22開催
|
203
203
|
- [ACコード 138ms 2020/10/5](https://atcoder.jp/contests/abc156/submissions/17205940)
|
204
|
-
- [ARC009: C
|
204
|
+
- [ARC009: C - 高橋君、24歳](https://atcoder.jp/contests/arc009/tasks/arc009_3) 2012/10/20開催
|
205
205
|
- [ACコード 1075ms 2020/10/5](https://atcoder.jp/contests/arc009/submissions/17206081)
|
206
206
|
- [ACコード 901ms 2020/10/5](https://atcoder.jp/contests/arc009/submissions/17208378)
|
207
207
|
|
@@ -221,8 +221,8 @@ p 12.to_m == 1 #=> true
|
|
221
221
|
- Rubyリファレンスマニュアル
|
222
222
|
- [class Numeric \(Ruby 2\.7\.0 リファレンスマニュアル\)](https://docs.ruby-lang.org/ja/latest/class/Numeric.html)
|
223
223
|
- その他
|
224
|
-
- [modint 構造体を使ってみませんか? \(C\+\+\)
|
225
|
-
- [Pythonでmodintを実装してみた
|
224
|
+
- [modint 構造体を使ってみませんか? \(C\+\+\) - noshi91のメモ](https://noshi91.hatenablog.com/entry/2019/03/31/174006)(2019/3/31)
|
225
|
+
- [Pythonでmodintを実装してみた - Qiita](https://qiita.com/wotsushi/items/c936838df992b706084c)(2019/4/1)
|
226
226
|
- [C#版のModIntのドキュメント](https://github.com/key-moon/ac-library-cs/blob/master/document_ja/modint.md)
|
227
227
|
|
228
228
|
|
data/document_ja/scc.md
CHANGED
@@ -50,17 +50,18 @@ graph.scc
|
|
50
50
|
|
51
51
|
## Verified
|
52
52
|
|
53
|
-
- [ALPC: G
|
54
|
-
- [
|
55
|
-
- [競プロ典型 90 問: 021 - Come Back in One Piece]
|
53
|
+
- [ALPC: G - SCC](https://atcoder.jp/contests/practice2/tasks/practice2_g)
|
54
|
+
- [Ruby2.7 1848ms 2022/11/22](https://atcoder.jp/contests/practice2/submissions/36708506)
|
55
|
+
- [競プロ典型 90 問: 021 - Come Back in One Piece](https://atcoder.jp/contests/typical90/tasks/typical90_u)
|
56
|
+
- [Ruby2.7 471ms 2021/6/15](https://atcoder.jp/contests/typical90/submissions/23487102)
|
56
57
|
|
57
58
|
# 参考リンク
|
58
59
|
|
59
60
|
- 当ライブラリ
|
60
|
-
- [当ライブラリの実装コード scc
|
61
|
-
- [当ライブラリの実装コード scc_test
|
61
|
+
- [当ライブラリの実装コード scc.rb](https://github.com/universato/ac-library-rb/blob/master/lib/scc.rb)
|
62
|
+
- [当ライブラリの実装コード scc_test.rb](https://github.com/universato/ac-library-rb/blob/master/test/scc_test.rb)
|
62
63
|
- 本家ライブラリ
|
63
|
-
- [本家ライブラリの実装コード scc
|
64
|
-
- [本家ライブラリのドキュメント scc
|
64
|
+
- [本家ライブラリの実装コード scc.hpp](https://github.com/atcoder/ac-library/blob/master/atcoder/scc.hpp)
|
65
|
+
- [本家ライブラリのドキュメント scc.md](https://github.com/atcoder/ac-library/blob/master/document_ja/scc.md)
|
65
66
|
- その他
|
66
|
-
- [強連結成分分解の意味とアルゴリズム
|
67
|
+
- [強連結成分分解の意味とアルゴリズム | 高校数学の美しい物語](https://mathtrain.jp/kyorenketsu)
|
data/document_ja/segtree.md
CHANGED
@@ -141,11 +141,11 @@ Segtree上で`0 <= l <= r`の範囲で、`f(prod(l, r))`の結果を二分探索
|
|
141
141
|
|
142
142
|
## Verified
|
143
143
|
|
144
|
-
- [ALPC: J
|
144
|
+
- [ALPC: J - Segment Tree](https://atcoder.jp/contests/practice2/tasks/practice2_j)
|
145
145
|
- [AC Code(884ms) max_right](https://atcoder.jp/contests/practice2/submissions/23196480)
|
146
146
|
- [AC Code(914ms) min_left](https://atcoder.jp/contests/practice2/submissions/23197311)
|
147
147
|
|
148
|
-
- [ABC185: F
|
148
|
+
- [ABC185: F - Range Xor Query](https://atcoder.jp/contests/abc185/tasks/abc185_f)
|
149
149
|
- xorのセグメントツリーの基本的な典型問題です。FenwickTree(BIT)をxorに改造するだけでも解けます。
|
150
150
|
- [ACコード(1538ms)](https://atcoder.jp/contests/abc185/submissions/18746817): 通常のSegtree解。
|
151
151
|
- [ACコード(821ms)](https://atcoder.jp/contests/abc185/submissions/18769200): FenwickTree(BIT)のxor改造版。
|
data/lib/convolution.rb
CHANGED
data/lib/dsu.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Disjoint Set Union
|
2
2
|
class DSU
|
3
|
-
def initialize(n)
|
3
|
+
def initialize(n = 0)
|
4
4
|
@n = n
|
5
5
|
@parent_or_size = Array.new(n, -1)
|
6
6
|
# root node: -1 * component size
|
@@ -35,6 +35,15 @@ class DSU
|
|
35
35
|
alias root leader
|
36
36
|
alias find leader
|
37
37
|
|
38
|
+
def [](a)
|
39
|
+
if @n <= a
|
40
|
+
@parent_or_size.concat([-1] * (a - @n + 1))
|
41
|
+
@n = @parent_or_size.size
|
42
|
+
end
|
43
|
+
|
44
|
+
@parent_or_size[a] < 0 ? a : (@parent_or_size[a] = self[@parent_or_size[a]])
|
45
|
+
end
|
46
|
+
|
38
47
|
def size(a)
|
39
48
|
-@parent_or_size[leader(a)]
|
40
49
|
end
|
@@ -42,6 +51,10 @@ class DSU
|
|
42
51
|
def groups
|
43
52
|
(0 ... @parent_or_size.size).group_by{ |i| leader(i) }.values
|
44
53
|
end
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
"<#{self.class}: @n=#{@n}, #{@parent_or_size}>"
|
57
|
+
end
|
45
58
|
end
|
46
59
|
|
47
60
|
UnionFind = DSU
|
data/lib/fenwick_tree.rb
CHANGED
data/lib/lazy_segtree.rb
CHANGED
@@ -153,9 +153,7 @@ class LazySegtree
|
|
153
153
|
sm = @e
|
154
154
|
|
155
155
|
loop do
|
156
|
-
while l.even?
|
157
|
-
l >>= 1
|
158
|
-
end
|
156
|
+
l >>= 1 while l.even?
|
159
157
|
unless g.call(@op.call(sm, @d[l]))
|
160
158
|
while l < @size
|
161
159
|
push(l)
|
@@ -183,9 +181,7 @@ class LazySegtree
|
|
183
181
|
|
184
182
|
loop do
|
185
183
|
r -= 1
|
186
|
-
while r > 1 && r.odd?
|
187
|
-
r /= 2
|
188
|
-
end
|
184
|
+
r /= 2 while r > 1 && r.odd?
|
189
185
|
unless g.call(@op.call(@d[r], sm))
|
190
186
|
while r < @size
|
191
187
|
push(r)
|
data/lib/max_flow.rb
CHANGED
@@ -36,39 +36,40 @@ class MaxFlow
|
|
36
36
|
|
37
37
|
# return edge = [from, to, cap, flow]
|
38
38
|
def [](i)
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
from, from_id = @pos[i]
|
40
|
+
|
41
|
+
to, to_id, cap = @g[from][from_id] # edge
|
42
|
+
_from, _from_id, flow = @g[to][to_id] # reverse edge
|
43
|
+
|
44
|
+
[from, to, cap + flow, flow]
|
42
45
|
end
|
43
46
|
alias get_edge []
|
44
47
|
alias edge []
|
45
48
|
|
46
49
|
def edges
|
47
|
-
@pos.map do |(from,
|
48
|
-
|
49
|
-
|
50
|
-
[from,
|
50
|
+
@pos.map do |(from, from_id)|
|
51
|
+
to, to_id, cap = @g[from][from_id]
|
52
|
+
_from, _from_id, flow = @g[to][to_id]
|
53
|
+
[from, to, cap + flow, flow]
|
51
54
|
end
|
52
55
|
end
|
53
56
|
|
54
57
|
def change_edge(i, new_cap, new_flow)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
58
|
+
from, from_id = @pos[i]
|
59
|
+
|
60
|
+
e = @g[from][from_id]
|
61
|
+
re = @g[e[0]][e[1]]
|
62
|
+
e[2] = new_cap - new_flow
|
63
|
+
re[2] = new_flow
|
59
64
|
end
|
60
65
|
|
61
66
|
def flow(s, t, flow_limit = 1 << 64)
|
62
|
-
level = Array.new(@n)
|
63
|
-
iter = Array.new(@n)
|
64
|
-
que = []
|
65
|
-
|
66
67
|
flow = 0
|
67
68
|
while flow < flow_limit
|
68
|
-
bfs(s, t
|
69
|
+
level = bfs(s, t)
|
69
70
|
break if level[t] == -1
|
70
71
|
|
71
|
-
iter
|
72
|
+
iter = [0] * @n
|
72
73
|
while flow < flow_limit
|
73
74
|
f = dfs(t, flow_limit - flow, s, level, iter)
|
74
75
|
break if f == 0
|
@@ -98,22 +99,22 @@ class MaxFlow
|
|
98
99
|
|
99
100
|
private
|
100
101
|
|
101
|
-
def bfs(s, t
|
102
|
-
level.
|
102
|
+
def bfs(s, t)
|
103
|
+
level = Array.new(@n, -1)
|
103
104
|
level[s] = 0
|
104
|
-
que
|
105
|
-
que << s
|
105
|
+
que = [s]
|
106
106
|
|
107
107
|
while (v = que.shift)
|
108
|
-
@g[v].each do |
|
109
|
-
next if
|
108
|
+
@g[v].each do |u, _, cap|
|
109
|
+
next if cap == 0 || level[u] >= 0
|
110
110
|
|
111
|
-
level[
|
112
|
-
return
|
111
|
+
level[u] = level[v] + 1
|
112
|
+
return level if u == t
|
113
113
|
|
114
|
-
que <<
|
114
|
+
que << u
|
115
115
|
end
|
116
116
|
end
|
117
|
+
level
|
117
118
|
end
|
118
119
|
|
119
120
|
def dfs(v, up, s, level, iter)
|
data/lib/modint.rb
CHANGED
@@ -4,7 +4,7 @@ require_relative './core_ext/modint.rb'
|
|
4
4
|
class ModInt < Numeric
|
5
5
|
class << self
|
6
6
|
def set_mod(mod)
|
7
|
-
raise ArgumentError unless mod.is_a?
|
7
|
+
raise ArgumentError unless mod.is_a?(Integer) && (1 <= mod)
|
8
8
|
|
9
9
|
$_mod = mod
|
10
10
|
$_mod_is_prime = ModInt.prime?(mod)
|
@@ -26,7 +26,7 @@ class ModInt < Numeric
|
|
26
26
|
|
27
27
|
def prime?(n)
|
28
28
|
return false if n <= 1
|
29
|
-
return true if n == 2
|
29
|
+
return true if (n == 2) || (n == 7) || (n == 61)
|
30
30
|
return false if (n & 1) == 0
|
31
31
|
|
32
32
|
d = n - 1
|
@@ -34,11 +34,11 @@ class ModInt < Numeric
|
|
34
34
|
[2, 7, 61].each do |a|
|
35
35
|
t = d
|
36
36
|
y = a.pow(t, n)
|
37
|
-
while t != n - 1
|
37
|
+
while (t != n - 1) && (y != 1) && (y != n - 1)
|
38
38
|
y = y * y % n
|
39
39
|
t <<= 1
|
40
40
|
end
|
41
|
-
return false if y != n - 1
|
41
|
+
return false if (y != n - 1) && ((t & 1) == 0)
|
42
42
|
end
|
43
43
|
true
|
44
44
|
end
|
data/lib/priority_queue.rb
CHANGED
@@ -13,11 +13,17 @@ class PriorityQueue
|
|
13
13
|
heapify
|
14
14
|
end
|
15
15
|
|
16
|
+
def self.[](*array, &comp)
|
17
|
+
new(array, &comp)
|
18
|
+
end
|
19
|
+
|
16
20
|
attr_reader :heap
|
21
|
+
alias to_a heap
|
17
22
|
|
18
23
|
# Push new element to the heap.
|
19
24
|
def push(item)
|
20
25
|
shift_down(0, @heap.push(item).size - 1)
|
26
|
+
self
|
21
27
|
end
|
22
28
|
|
23
29
|
alias << push
|
@@ -46,6 +52,14 @@ class PriorityQueue
|
|
46
52
|
@heap.empty?
|
47
53
|
end
|
48
54
|
|
55
|
+
def size
|
56
|
+
@heap.size
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
"<#{self.class}: @heap:(#{heap.join(', ')}), @comp:<#{@comp.class} #{@comp.source_location.join(':')}>>"
|
61
|
+
end
|
62
|
+
|
49
63
|
private
|
50
64
|
|
51
65
|
def heapify
|
data/lib/scc.rb
CHANGED
@@ -3,17 +3,17 @@ class SCC
|
|
3
3
|
# initialize graph with n vertices
|
4
4
|
def initialize(n)
|
5
5
|
@n = n
|
6
|
-
@edges = []
|
6
|
+
@edges = Array.new(n) { [] }
|
7
7
|
end
|
8
8
|
|
9
9
|
# add directed edge
|
10
10
|
def add_edge(from, to)
|
11
|
-
unless 0 <= from && from < @n
|
11
|
+
unless 0 <= from && from < @n && 0 <= to && to < @n
|
12
12
|
msg = "Wrong params: from=#{from} and to=#{to} must be in 0...#{@n}"
|
13
13
|
raise ArgumentError.new(msg)
|
14
14
|
end
|
15
15
|
|
16
|
-
@edges <<
|
16
|
+
@edges[from] << to
|
17
17
|
self
|
18
18
|
end
|
19
19
|
|
@@ -28,7 +28,7 @@ class SCC
|
|
28
28
|
|
29
29
|
# returns list of strongly connected components
|
30
30
|
# the components are sorted in topological order
|
31
|
-
# O(@n + @edges.size)
|
31
|
+
# O(@n + @edges.sum(&:size))
|
32
32
|
def scc
|
33
33
|
group_num, ids = scc_ids
|
34
34
|
groups = Array.new(group_num) { [] }
|
@@ -39,47 +39,49 @@ class SCC
|
|
39
39
|
private
|
40
40
|
|
41
41
|
def scc_ids
|
42
|
-
|
43
|
-
|
44
|
-
visited
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
42
|
+
now_ord = 0
|
43
|
+
|
44
|
+
visited = []
|
45
|
+
low = Array.new(@n, 1 << 60)
|
46
|
+
ord = Array.new(@n, -1)
|
47
|
+
group_num = 0
|
48
|
+
|
49
|
+
(0...@n).each do |v|
|
50
|
+
next if ord[v] != -1
|
51
|
+
|
52
|
+
stack = [[v, 0]]
|
53
|
+
|
54
|
+
while (v, i = stack.pop)
|
55
|
+
if i == 0
|
56
|
+
visited << v
|
57
|
+
low[v] = ord[v] = now_ord
|
58
|
+
now_ord += 1
|
59
|
+
end
|
60
|
+
|
61
|
+
while i < @edges[v].size
|
62
|
+
u = @edges[v][i]
|
63
|
+
i += 1
|
64
|
+
|
65
|
+
if ord[u] == -1
|
66
|
+
stack << [v, i] << [u, 0]
|
67
|
+
break 1
|
68
|
+
end
|
69
|
+
end and next
|
70
|
+
|
71
|
+
low[v] = [low[v], @edges[v].map { |e| low[e] }.min || @n].min
|
72
|
+
next if low[v] != ord[v]
|
73
|
+
|
74
|
+
while (u = visited.pop)
|
75
|
+
low[u] = @n
|
76
|
+
ord[u] = group_num
|
63
77
|
break if u == v
|
64
78
|
end
|
65
79
|
group_num += 1
|
66
|
-
end
|
67
|
-
}
|
68
|
-
@n.times { |i| dfs.(i) if ord[i] == -1 }
|
69
|
-
ids = ids.map { |x| group_num - 1 - x }
|
70
|
-
[group_num, ids]
|
71
|
-
end
|
72
80
|
|
73
|
-
|
74
|
-
start = [0] * (@n + 1)
|
75
|
-
elist = [nil] * @edges.size
|
76
|
-
@edges.each { |(i, _)| start[i + 1] += 1 }
|
77
|
-
@n.times { |i| start[i + 1] += start[i] }
|
78
|
-
counter = start.dup
|
79
|
-
@edges.each do |(i, j)|
|
80
|
-
elist[counter[i]] = j
|
81
|
-
counter[i] += 1
|
81
|
+
end
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
|
+
ord.map! { |e| group_num - e - 1 }
|
85
|
+
[group_num, ord]
|
84
86
|
end
|
85
87
|
end
|
data/lib/two_sat.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module AcLibraryRb
|
2
2
|
# Disjoint Set Union
|
3
3
|
class DSU
|
4
|
-
def initialize(n)
|
4
|
+
def initialize(n = 0)
|
5
5
|
@n = n
|
6
6
|
@parent_or_size = Array.new(n, -1)
|
7
7
|
# root node: -1 * component size
|
@@ -36,6 +36,15 @@ module AcLibraryRb
|
|
36
36
|
alias root leader
|
37
37
|
alias find leader
|
38
38
|
|
39
|
+
def [](a)
|
40
|
+
if @n <= a
|
41
|
+
@parent_or_size.concat([-1] * (a - @n + 1))
|
42
|
+
@n = @parent_or_size.size
|
43
|
+
end
|
44
|
+
|
45
|
+
@parent_or_size[a] < 0 ? a : (@parent_or_size[a] = self[@parent_or_size[a]])
|
46
|
+
end
|
47
|
+
|
39
48
|
def size(a)
|
40
49
|
-@parent_or_size[leader(a)]
|
41
50
|
end
|
@@ -43,6 +52,10 @@ module AcLibraryRb
|
|
43
52
|
def groups
|
44
53
|
(0 ... @parent_or_size.size).group_by{ |i| leader(i) }.values
|
45
54
|
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
"<#{self.class}: @n=#{@n}, #{@parent_or_size}>"
|
58
|
+
end
|
46
59
|
end
|
47
60
|
|
48
61
|
UnionFind = DSU
|
@@ -154,9 +154,7 @@ module AcLibraryRb
|
|
154
154
|
sm = @e
|
155
155
|
|
156
156
|
loop do
|
157
|
-
while l.even?
|
158
|
-
l >>= 1
|
159
|
-
end
|
157
|
+
l >>= 1 while l.even?
|
160
158
|
unless g.call(@op.call(sm, @d[l]))
|
161
159
|
while l < @size
|
162
160
|
push(l)
|
@@ -184,9 +182,7 @@ module AcLibraryRb
|
|
184
182
|
|
185
183
|
loop do
|
186
184
|
r -= 1
|
187
|
-
while r > 1 && r.odd?
|
188
|
-
r /= 2
|
189
|
-
end
|
185
|
+
r /= 2 while r > 1 && r.odd?
|
190
186
|
unless g.call(@op.call(@d[r], sm))
|
191
187
|
while r < @size
|
192
188
|
push(r)
|