ac-library-rb 0.7.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92f162f1c30df36b5602b074dc6c93dcb850a9f528cf3a81aea5d28c7d6e25b7
4
- data.tar.gz: 54d7ee1109261c6e873fa30d7c2d778702f942037aa9e4ed2597d624af7c5c4c
3
+ metadata.gz: 22006092d0cd212252ead6bc78fa5e37c6561f2fc9117d2bb92c9bc35d9652b2
4
+ data.tar.gz: 8ffdfae56a8b4065ae0698d1a99082554cddc63793847f526ce1b97b56dce7e5
5
5
  SHA512:
6
- metadata.gz: 4bbf58133808113aeaca23eadc803bdd5a6d7f6834137c5e01dcc23b5a61e4d7e718ee37bed8dc27f967b3d63162cf584ef0e5ba508e315fb020d7e1fad7b0b1
7
- data.tar.gz: 40143c6a526626d086d3f639f1b6d8c95c4da9a3407249118bd8cf6837436c2741a34ff806285137598003debc95a3853337d863da567f24c9e637597982e3a9
6
+ metadata.gz: 7786082b3706d8f4381e544d506e55fbc846621c34c91342b6248110a9d6310eff38e6f2d5d2d3230d10580a331439a4e027af2b43e0bdb38f9f150695df759f
7
+ data.tar.gz: 3dfc4a42e293c08699c9e8926114ee757f1b501988672a862760545d155d91632985d36a10e0b0fd8a3aa654f68fb975baccccb37cb09d0c6313e82748ee6898
@@ -1,3 +1,3 @@
1
1
  module AcLibraryRb
2
- VERSION = "0.7.0".freeze
2
+ VERSION = "1.0.0".freeze
3
3
  end
data/lib/scc.rb CHANGED
@@ -3,7 +3,7 @@ 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
@@ -13,7 +13,7 @@ class SCC
13
13
  raise ArgumentError.new(msg)
14
14
  end
15
15
 
16
- @edges << [from, to]
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
- start, elist = csr
43
- now_ord = group_num = 0
44
- visited, low, ord, ids = [], [], [-1] * @n, []
45
- dfs = ->(v) {
46
- low[v] = ord[v] = now_ord
47
- now_ord += 1
48
- visited << v
49
- (start[v]...start[v + 1]).each do |i|
50
- to = elist[i]
51
- low[v] = if ord[to] == -1
52
- dfs.(to)
53
- [low[v], low[to]].min
54
- else
55
- [low[v], ord[to]].min
56
- end
57
- end
58
- if low[v] == ord[v]
59
- loop do
60
- u = visited.pop
61
- ord[u] = @n
62
- ids[u] = group_num
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
- def csr
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
- [start, elist]
83
+
84
+ ord.map! { |e| group_num - e - 1 }
85
+ [group_num, ord]
84
86
  end
85
87
  end
@@ -4,7 +4,7 @@ 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
@@ -14,7 +14,7 @@ module AcLibraryRb
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
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ac-library-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.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: 2022-11-26 00:00:00.000000000 Z
11
+ date: 2023-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prime