Problem:
E: Arai's - Arai's -

問題

スクールアイドル時代から、国民的人気を誇ってきた女性アイドルグループArai's。今では、たくさんの「あらい」さんが所属する大規模なグループとして、世界レベルで活躍している。そして今日、新たなるプロジェクトの始動が決定した。彼女たちは、小さなユニットをいくつか結成することで、さらなる売上の向上を試みることになったのである。

Arai'sには「荒井」さんがA人，「新井」さんがB人在籍しており、合計でA+B人の「あらい」さんからなる。新ユニットは、「荒井」さん一人と「新井」さん一人のペアで構成する。（ここで、同じ「あらい」さんが複数のユニットに所属していはいけない。）ただし、ある「荒井」さんが一部の「新井」さんのことを良く思っていないうえに、同様にある「新井」さんが一部の「荒井」さんのことを良く思っていない。「あらい」さんたちはユニットを組む際に、良く思っていない「あらい」さんをペアとして認めてくれず、一方でも認めてくれなければユニットを組むことはできない。

Arai'sのマネージャーであるあなたは、なるべくたくさんのユニットを作りたいと考えているが、メンバーの交友関係からその限界を感じていた。そこであなたは、「あらい」さんたちと個別に面談し、ユニットを組ませたい「あらい」さんについての、良い噂を聞かせることを考えた。面談をした「あらい」さんは、噂に聞いた「あらい」さんを見直し、ユニットのペアとして認めるようになる。

しかし、あなたはそれほど時間をとることができないため、最大K回までしか噂を聞かせることができない。あなたは限られた時間の中で、結成できるユニットの数を最大化しようと試みた。あなたが結成できるユニットの数の最大値を求めよ。

入力形式

A B K
a_1
...
a_A
b_1
...
b_B

1行目には、「荒井」さんの人数Aと「新井」さんの人数B (1 \≤ A, B \≤ 200でありA, Bは整数)、噂を聞かせることができる人数K (0 \≤ K \≤ 200でありKは整数)が空白区切りで与えられる。

続くA行には、それぞれ長さBの0と1のみからなる文字列が与えられる。そのうちi行目の文字列a_iのj文字目が1であるとき、i番目の「荒井」さんはj番目の「新井」さんを良く思っていない。

続くB行には、それぞれ長さAの0と1のみからなる文字列が与えられる。そのうちi行目の文字列b_iのj文字目が1であるとき、i番目の「新井」さんはj番目の「荒井」さんを良く思っていない。

出力形式

あなたが結成できるユニット数の最大値を1行に出力せよ。

入力例1

3 3 4
111
111
111
111
111
111

出力例1

2

入力例2

3 3 2
101
100
010
001
011
111

出力例2

3

入力例3

5 6 3
101101
110110
010111
110110
110111
01010
10101
11101
01011
11011
11011

出力例3

4

Solution in Scala (judge verdict: Accepted)

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
object Main extends App {
  import scala.io.StdIn._


  val Array(a, b, k) = readLine.trim.split(' ').map(_.toInt)
  val state = Array.tabulate(a){_ ⇒ Array.tabulate(b){_ ⇒ 0}}
  for (i ← 0 until a){
    val s = readLine.trim.map(_.asDigit)
    for (j ← s.indices){
      state(i)(j) += s(j)
    }
  }
  for (i ← 0 until b){
    val s = readLine.trim.map(_.asDigit)
    for (j ← s.indices){
      state(j)(i) += s(j)
    }
  }
  println(calMinCostFlow(a, b, state, k))

  def calMinCostFlow(aSize: Int, bSize: Int, costs: Array[Array[Int]], k: Int): Int = {
    val start = 0
    val goal = aSize + bSize + 1
    val nodes = Array.tabulate(goal + 1){_ ⇒ ArrayBuffer[Edge]()}.let{a ⇒
      for (i ← 1 to aSize){
        a(i).append(Edge(start, 0, a(start).length, false))
        a(start).append(Edge(i, 0, 0, true))
      }
      for (i ← (aSize + 1) until goal){
        a(i).append(Edge(goal, 0, a(goal).length, true))
        a(goal).append(Edge(i, 0, 0, false))
      }
      for (from ← 0 until aSize; to ← 0 until bSize){
        val i = from + 1
        val j = to + aSize + 1
        a(i).append(Edge(j, costs(from)(to), a(j).length, true))
        a(j).append(Edge(i, -costs(from)(to), a(i).length - 1, false))
      }
      a.map(_.toArray)
    }
    val minCost = Array.tabulate(nodes.length){_ ⇒ Int.MaxValue}.also(_(0) = 0)
    val potential = Array.tabulate(nodes.length){_ ⇒ 0}
    val queue = mutable.PriorityQueue()(Ordering.by[(Int, Int), Int](_._2))
    val prevEdge = Array.tabulate(nodes.length){_ ⇒ nodes(0)(0)}
    var cost = 0
    var count = 0
    var canAddPair = true
    while (canAddPair){
      for (i ← minCost.indices.tail) minCost(i) = Int.MaxValue
      queue.enqueue((0, 0))
      while(queue.nonEmpty){
        val (current, cost) = queue.dequeue()
        if (minCost(current) == cost){
          for (edge ← nodes(current) if edge.canUse) {
            if (minCost(edge.to) > potential(current) + edge.cost - potential(edge.to) + cost) {
              prevEdge(edge.to) = nodes(edge.to)(edge.pair)
              minCost(edge.to) = potential(current) + edge.cost - potential(edge.to) + cost
              queue.enqueue((edge.to, minCost(edge.to)))
            }
          }
        }
      }
      if (minCost(goal) != Int.MaxValue && minCost(goal) + cost <= k){
        cost += minCost(goal)
        count += 1
        var last = goal
        while(last != start){
          val prev = prevEdge(last)
          prev.canUse = true
          nodes(prev.to)(prev.pair).canUse = false
          last = prev.to
        }
        for (i ← 1 until goal) potential(i) += minCost(i)
      }else canAddPair = false
    }
    count
  }
  case class Edge(to: Int, cost: Int, pair: Int, var canUse: Boolean)
  implicit class Scope[T](val value: T) extends AnyVal {
    @inline def also(@inline func: T ⇒ Unit): T = {
      func(value)
      value
    }
    @inline def let[A](@inline func: T ⇒ A): A = func(value)
  }
}