結果
| 問題 |
No.1477 Lamps on Graph
|
| コンテスト | |
| ユーザー |
yuruhiya
|
| 提出日時 | 2021-04-16 21:58:04 |
| 言語 | Crystal (1.14.0) |
| 結果 |
AC
|
| 実行時間 | 79 ms / 2,000 ms |
| コード長 | 5,428 bytes |
| コンパイル時間 | 17,130 ms |
| コンパイル使用メモリ | 296,008 KB |
| 実行使用メモリ | 15,104 KB |
| 最終ジャッジ日時 | 2024-07-03 01:41:47 |
| 合計ジャッジ時間 | 18,717 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 38 |
ソースコード
# require "template"
lib C
fun strtoll(s : UInt8*, p : UInt8**, b : Int32) : Int64
end
class String
def to_i64
C.strtoll(self, nil, 10)
end
end
# require "graph"
struct Edge(T)
property to : Int32
property cost : T
def initialize(@to : Int32, @cost : T)
end
end
struct Edge2(T)
property from : Int32
property to : Int32
property cost : T
def initialize(@from : Int32, @to : Int32, @cost : T)
end
def reverse
Edge2(T).new(to, from, cost)
end
end
class Graph(T)
getter size : Int32
getter graph : Array(Array(Edge(T)))
def initialize(@size : Int32)
raise ArgumentError.new("Negative graph size: #{size}") unless size >= 0
@graph = Array.new(size) { Array(Edge(T)).new }
end
def initialize(@size, edges : Array(Edge2(T)), undirected : Bool)
raise ArgumentError.new("Negative graph size: #{size}") unless size >= 0
@graph = Array.new(size) { Array(Edge(T)).new }
edges.each do |edge|
@graph[edge.from] << Edge.new(edge.to, edge.cost)
@graph[edge.to] << Edge.new(edge.from, edge.cost) if undirected
end
end
def add_edge(i : Int32, j : Int32, cost : T)
raise IndexError.new unless 0 <= i < size
raise IndexError.new unless 0 <= j < size
graph[i] << Edge(T).new(j, cost)
graph[j] << Edge(T).new(i, cost)
end
def add_edge_directed(i : Int32, j : Int32, cost : T)
raise IndexError.new unless 0 <= i < size
raise IndexError.new unless 0 <= j < size
graph[i] << Edge(T).new(j, cost)
end
def [](i : Int32)
graph[i]
end
def each_edge : Nil
(0...size).each do |v|
graph[v].each do |edge|
yield Edge2(T).new(v, edge.to, edge.cost)
end
end
end
def edges : Array(Edge2(T))
result = [] of Edge2(T)
each_edge do |edge|
result << edge
end
result
end
end
# require "atcoder/PriorityQueue"
# ac-library.cr by hakatashi https://github.com/google/ac-library.cr
#
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module AtCoder
# Implements standard priority queue like [std::priority_queue](https://en.cppreference.com/w/cpp/container/priority_queue).
#
# ```
# q = AtCoder::PriorityQueue(Int64).new
# q << 1_i64
# q << 3_i64
# q << 2_i64
# q.pop # => 3
# q.pop # => 2
# q.pop # => 1
# ```
class PriorityQueue(T)
getter heap : Array(T)
def initialize
initialize(&.itself)
end
# Initializes queue with the custom comperator.
#
# ```
# q = AtCoder::PriorityQueue(Int64).new {|n| -n}
# q << 1_i64
# q << 3_i64
# q << 2_i64
# q.pop # => 1
# q.pop # => 2
# q.pop # => 3
# ```
def initialize(&block : T -> (Int8 | Int16 | Int32 | Int64 | UInt8 | UInt16 | UInt32 | UInt64))
@heap = Array(T).new
@priority_proc = block
end
# Pushes value into the queue.
def push(v : T)
@heap << v
index = @heap.size - 1
while index != 0
parent = (index - 1) // 2
if @priority_proc.call(@heap[parent]) >= @priority_proc.call(@heap[index])
break
end
@heap[parent], @heap[index] = @heap[index], @heap[parent]
index = parent
end
end
# Alias of `push`
def <<(v : T)
push(v)
end
# Pops value from the queue.
def pop
if @heap.size == 0
return nil
end
if @heap.size == 1
return @heap.pop
end
ret = @heap.first
@heap[0] = @heap.pop
index = 0
while index * 2 + 1 < @heap.size
child = if index * 2 + 2 < @heap.size && @priority_proc.call(@heap[index * 2 + 1]) < @priority_proc.call(@heap[index * 2 + 2])
index * 2 + 2
else
index * 2 + 1
end
if @priority_proc.call(@heap[index]) >= @priority_proc.call(@heap[child])
break
end
@heap[child], @heap[index] = @heap[index], @heap[child]
index = child
end
ret
end
# Returns `true` if the queue is empty.
delegate :empty?, to: @heap
# Returns size of the queue.
delegate :size, to: @heap
end
end
n, m = read_line.split.map(&.to_i)
a = read_line.split.map(&.to_i)
edges = (0...m).flat_map {
u, v = read_line.split.map(&.to_i.pred)
e = Edge2(Nil).new(u, v, nil)
[e, e.reverse]
}
k = read_line.to_i
b = read_line.split.map(&.to_i.pred)
graph = Graph.new(n, edges.select { |e| a[e.from] < a[e.to] }, undirected: false)
count_in = [0] * n
graph.each_edge do |e|
count_in[e.to] += 1
end
flag = [false] * n
b.each { |i| flag[i] = true }
que = Deque.new((0...n).select { |i| count_in[i] == 0 })
ans = [] of Int32
while v = que.shift?
op = flag[v]
if op
flag[v] = false
ans << v
end
graph[v].each do |e|
count_in[e.to] -= 1
flag[e.to] = !flag[e.to] if op
que << e.to if count_in[e.to] == 0
end
end
if flag.none?
puts ans.size, ans.join('\n', &.succ)
else
puts -1
end
yuruhiya