import scala.collection.mutable

object Main extends App {

  import scala.io.StdIn._
  import scala.math._

  val Array(n, m, s, t) = readLine.trim.split(' ').map(_.toInt)
  val nodes = Array.tabulate(n){_ ⇒ Nil: List[(Int, Int, Int)]}
  for (_ ← 0 until m){
    val Array(u, v, d, c) = readLine.trim.split(' ').map(_.toInt)
    nodes(u - 1) ::= (v - 1, d, c)
  }
  println(
    calMaxFluid(minPathGraph(nodes).map{_.toMap}, s - 1, t - 1)
  )
  def minPathGraph(nodes: Array[List[(Int, Int, Int)]]): Array[List[(Int, Int)]] = {
    val minCost = Array.tabulate(n) { _ ⇒ Int.MaxValue }.also { arr ⇒ arr(s - 1) = 0 }
    val prevNode = Array.tabulate(n) { _ ⇒ Nil: List[(Int, Int)] }
    val priorityQueue = mutable.PriorityQueue()(Ordering.by[(Int, Int), Int](_._2).reverse).also { que ⇒ que.enqueue((s - 1, 0)) }
    while (priorityQueue.nonEmpty) {
      val (top, distance) = priorityQueue.dequeue()
      if (minCost(top) == distance) {
        for ((to, d, fluid) ← nodes(top)) {
          if (minCost(to) > distance + d) {
            minCost(to) = distance + d
            prevNode(to) = List((top, fluid))
            priorityQueue.enqueue((to, d + distance))
          } else if (minCost(to) == distance + d) {
            prevNode(to) ::= (top, fluid)
          }
        }
      }
    }
    val result = Array.tabulate(n){_ ⇒ Nil: List[(Int, Int)]}
    for (to ← prevNode.indices){
      for ((from, cost) ← prevNode(to)){
        result(from) ::= (to, cost)
      }
    }
    result
  }
  def calMaxFluid(nodes: Array[Map[Int, Int]], start: Int, goal: Int): Int = {
    val queue = mutable.Queue[Int]()
    val cost = Array.tabulate(nodes.length){_ ⇒ Array.tabulate(nodes.length){_ ⇒ 0}}
    for (from ← nodes.indices){
      for ((to, c) ← nodes(from)){
        cost(from)(to) = c
      }
    }
    val edges = nodes.map{map ⇒ map.keys.toSet}
    val prev = Array.tabulate(nodes.length){_ ⇒ -1}
    var canReach = true
    var result = 0
    while (canReach){
      canReach = false
      queue.enqueue(start)
      while(queue.nonEmpty && !canReach){
        val top = queue.dequeue()
        for (next ← edges(top)){
          if (next != start && prev(next) == -1){
            prev(next) = top
            queue.enqueue(next)
            if (next == goal) canReach = true
          }
        }
      }
      if (canReach){
        queue.clear()
        var from = prev(goal)
        var to = goal
        var minFluid = Int.MaxValue
        while (from != -1){
          minFluid = math.min(minFluid, nodes(from)(to))
          to = from
          from = prev(from)
        }
        result += minFluid
        from = prev(goal)
        to = goal
        while (from != -1){
          cost(from)(to) -= minFluid
          if (cost(from)(to) == 0){
            edges(from) -= to
          }
          cost(to)(from) += minFluid
          if (cost(to)(from) == minFluid){
            edges(to) += from
          }
          to = from
          from = prev(from)
        }
        prev.indices.foreach(i ⇒ prev(i) = -1)
      }
    }
    result
  }


  implicit class Extension[T](val value :T){
    def also(func: T ⇒ Unit): T = {
      func(value)
      value
    }
    def let[R](func: T ⇒ R): R = func(value)
  }
}


Measured memory_bytes: 51964