ac-library-rb 0.7.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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