結果

問題 No.1479 Matrix Eraser
ユーザー yuruhiyayuruhiya
提出日時 2021-04-20 18:00:19
言語 Crystal
(1.11.2)
結果
AC  
実行時間 315 ms / 3,000 ms
コード長 3,988 bytes
コンパイル時間 21,902 ms
コンパイル使用メモリ 260,812 KB
実行使用メモリ 57,456 KB
最終ジャッジ日時 2023-09-17 08:49:56
合計ジャッジ時間 28,671 ms
ジャッジサーバーID
(参考情報)
judge11 / judge14
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,380 KB
testcase_01 AC 3 ms
4,484 KB
testcase_02 AC 2 ms
4,420 KB
testcase_03 AC 3 ms
4,444 KB
testcase_04 AC 2 ms
4,448 KB
testcase_05 AC 3 ms
4,496 KB
testcase_06 AC 3 ms
4,424 KB
testcase_07 AC 28 ms
11,104 KB
testcase_08 AC 49 ms
16,852 KB
testcase_09 AC 116 ms
28,836 KB
testcase_10 AC 247 ms
56,948 KB
testcase_11 AC 158 ms
30,988 KB
testcase_12 AC 36 ms
15,104 KB
testcase_13 AC 50 ms
17,196 KB
testcase_14 AC 41 ms
15,144 KB
testcase_15 AC 10 ms
7,260 KB
testcase_16 AC 45 ms
16,312 KB
testcase_17 AC 315 ms
57,284 KB
testcase_18 AC 312 ms
57,224 KB
testcase_19 AC 310 ms
57,160 KB
testcase_20 AC 302 ms
57,456 KB
testcase_21 AC 299 ms
57,288 KB
testcase_22 AC 306 ms
57,220 KB
testcase_23 AC 298 ms
57,188 KB
testcase_24 AC 297 ms
57,272 KB
testcase_25 AC 305 ms
57,108 KB
testcase_26 AC 302 ms
57,380 KB
testcase_27 AC 177 ms
30,852 KB
testcase_28 AC 177 ms
30,852 KB
testcase_29 AC 176 ms
30,816 KB
testcase_30 AC 173 ms
30,848 KB
testcase_31 AC 177 ms
30,796 KB
testcase_32 AC 66 ms
29,476 KB
testcase_33 AC 67 ms
30,760 KB
testcase_34 AC 67 ms
29,276 KB
testcase_35 AC 67 ms
29,100 KB
testcase_36 AC 66 ms
30,524 KB
testcase_37 AC 49 ms
26,624 KB
testcase_38 AC 171 ms
40,604 KB
testcase_39 AC 252 ms
57,320 KB
testcase_40 AC 3 ms
4,380 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
In Main.cr:163:15

 163 | edges = Array.product((0...h).to_a, (0...w).to_a).group_by { |(i, j)|
                     ^------
Warning: Deprecated Array(T).product. Use `Indexable.cartesian_product(indexables : Indexable(Indexable))` instead

A total of 1 warnings were found.

ソースコード

diff #

# 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/bipartite_matching"
# require "./graph"
struct Edge(T)
  property to : Int32
  property cost : T

  def initialize(@to : Int32, @cost : T)
  end

  def to_s(io) : Nil
    io << {to, cost}
  end

  def inspect(io) : Nil
    io << "->#{to}(#{cost})"
  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

  def to_s(io) : Nil
    io << {from, to, cost}
  end

  def inspect(io) : Nil
    io << "#{from}->#{to}(#{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

class BipartiteMatching
  getter left : Int32
  getter right : Int32
  getter graph : Graph(Nil)

  def initialize(@left, @right)
    raise ArgumentError.new "Negative left vertexes size: #{left}" unless left >= 0
    raise ArgumentError.new "Negative right vertexes size: #{right}" unless right >= 0
    @graph = Graph(Nil).new(left)
    @left_match = Array(Int32).new(left, -1)
    @right_match = Array(Int32).new(right, -1)
    @used = Array(Bool).new(left, false)
  end

  def add_edge(l : Int32, r : Int32)
    raise IndexError.new unless 0 <= l < left
    raise IndexError.new unless 0 <= r < right
    graph[l] << Edge.new(r, nil)
    self
  end

  def add_edge(edges : Array(Edge2(Nil)))
    edges.each do |edge|
      add_edge(edge.from, edge.to)
    end
    self
  end

  private def dfs(v : Int32) : Bool
    return false if @used[v]
    @used[v] = true
    graph[v].each do |edge|
      if @right_match[edge.to] == -1 || dfs(@right_match[edge.to])
        @left_match[v], @right_match[edge.to] = edge.to, v
        return true
      end
    end
    return false
  end

  def solve : Int32
    result = 0
    update = true
    while update
      update = false
      (0...left).each do |i|
        if @left_match[i] == -1 && dfs(i)
          update = true
          result += 1
        end
      end
      @used.fill(false) if update
    end
    result
  end
end

h, w = read_line.split.map(&.to_i)
a = (1..h).map { read_line.split.map(&.to_i) }

l, r = 0, 0
edges = Array.product((0...h).to_a, (0...w).to_a).group_by { |(i, j)|
  a[i][j]
}.flat_map { |val, points|
  next [] of Edge2(Nil) if val == 0
  row = {} of Int32 => Int32
  column = {} of Int32 => Int32
  points.map do |(y, x)|
    ll = row[y]? || (row[y] = (l += 1) - 1)
    rr = column[x]? || (column[x] = (r += 1) - 1)
    Edge2.new(ll, rr, nil)
  end
}

puts BipartiteMatching.new(l, r).add_edge(edges).solve
0