Problem:
Movie

Problem

太郎君は夏休みの間、毎日１つの映画を近所の映画館で見ることにしました。
（太郎君の夏休みは8月1日から8月31日までの31日間あります。）

その映画館では、夏休みの間にn つの映画が上映されることになっています。
それぞれの映画には 1 から n までの番号が割り当てられており、i 番目の映画は8月 ai 日から8月 bi 日の間だけ上映されます。

太郎君は映画を見た時、それが初めて見る映画だった場合は 100 の幸福度を得ることができます。
しかし、過去に 1 度でも見たことのある映画だった場合は 50 の幸福度を得ます。

太郎君は上映される映画の予定表をもとに、夏休みの計画を立てることにしました。
太郎君が得られる幸福度の合計値が最大になるように映画を見たときの合計値を求めてください。

どの日も必ず1つ以上の映画が上映されていることが保証されます。

Input

入力は以下の形式で与えられる。

n
a1 b1
a2 b2
...
an bn

1行目に、1つの整数 n が与えられる。
2行目からの n 行のうち i 行目には 2 つの整数 ai, bi が空白区切りで与えられる。

Constraints

1 ≤ n ≤ 100

1 ≤ ai ≤ bi ≤ 31 (1 ≤ i ≤ n)

Output

太郎君の得られる幸福度の合計値の最大値を出力せよ。

Sample Input 1

4
1 31
2 2
2 3
3 3

Sample Output 1

1700

Sample Input 2

5
1 10
10 20
20 21
22 31
4 20

Sample Output 2

1800

Solution in Scala (judge verdict: Accepted)

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

object Main extends App {
  import scala.io.StdIn._



  val n = readInt
  val movies = Array.tabulate(n){_ ⇒
    val Array(from, to) = readLine.trim.split(' ').map(_.toInt)
    Movie(from, to)
  }
  val (source, drain, nodes) = makeGraph(movies)
  println(3100 - calMinCost(nodes, source, drain, 31))
  def makeGraph(movies: Array[Movie]): (Int, Int, Array[Array[Edge]]) = {
    val result = Array.tabulate(31 + movies.length * 2 + 2){_ ⇒ ArrayBuffer[Edge]()}
    val days = 0 until 31
    val movieFirstTime = movies.zipWithIndex.map(m ⇒ (m._1, m._2 + 31))
    val movieSecondTime = movies.zipWithIndex.map(m ⇒ (m._1, m._2 + 31 + movies.length))
    val source = 31 + movies.length * 2
    val drain = source + 1
    for (day ← days){
      result(day).append(Edge(source, result(source).length, 0, 0))
      result(day).append(Edge(drain, result(drain).length, 100, 1))
      result(source).append(Edge(day, 0, 0, 1))
      result(drain).append(Edge(day, 1, -100, 0))
    }
    for ((m, movie) ← movieFirstTime){
      result(movie).append(Edge(drain, result(drain).length, 0, 1))
      result(drain).append(Edge(movie, 0, 0, 0))
      for (day ← m.range.map(_ - 1)){
        result(movie).append(Edge(day, result(day).length, 0, 0))
        result(day).append(Edge(movie, result(movie).length - 1, 0, 1))
      }
    }
    for ((m, movie) ← movieSecondTime){
      result(movie).append(Edge(drain, result(drain).length, 0, 100))
      result(drain).append(Edge(movie, 0, 0, 0))
      for (day ← m.range.map(_ - 1)){
        result(movie).append(Edge(day, result(day).length, -50, 0))
        result(day).append(Edge(movie, result(movie).length - 1, 50, 1))
      }
    }
    (source, drain, result.map(_.toArray))
  }
  case class Movie(from: Int, to: Int) {
    def range = from to to
  }
  def calMinCost(nodes: Array[Array[Edge]], source: Int, drain: Int, flow: Int): Int = {
    val minCost = Array.tabulate(nodes.length){_ ⇒ Int.MaxValue}
    val potential = Array.tabulate(nodes.length){_ ⇒ 0}
    val queue = mutable.PriorityQueue()(Ordering.by[(Int, Int), Int](_._2).reverse)
    val revEdge = Array.tabulate(nodes.length){_ ⇒ Edge(0, 0, 0, 0)}
    var result = 0
    for (_ ← 0 until flow){
      minCost.indices.foreach(i ⇒ minCost(i) = Int.MaxValue)
      minCost(source) = 0
      queue.enqueue((source, 0))
      while(queue.nonEmpty){
        val (top, cost) = queue.dequeue()
        if (minCost(top) == cost && top != drain){
          for (Edge(to, pair, c, flow) ← nodes(top) if flow > 0){
            if (minCost(to) > potential(to) + c - potential(top) + cost) {
              minCost(to) = potential(to) + c - potential(top) + cost
              revEdge(to) = nodes(to)(pair)
              queue.enqueue((to, minCost(to)))
            }
          }
        }
      }
      result += minCost(drain)
      var last = drain
      while(last != source){
        val Edge(from, pair, _, _) = revEdge(last)
        nodes(from)(pair).flow -= 1
        revEdge(last).flow += 1
        last = from
      }
      for (i ← potential.indices if i != source && i != drain) potential(i) += minCost(i)
    }
    result
  }
  case class Edge(to: Int, pair: Int, cost: Int, var flow: Int)
  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)
  }
}