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

  val Array(n, m, s, g) = readLine.trim.split(' ').map(_.toInt)
  val bus = Array.tabulate(m){i ⇒
    val Array(u, v, t, c) = readLine.trim.split(' ').map(_.toInt)
    Bus(i, u - 1, v - 1, t, t + c)
  }.sortBy(_.start)
  val busStop = Array.fill(n){ArrayBuffer[Bus]()}
  val rank = Array.fill(m){0}
  for (b ← bus) {
    busStop(b.from).append(b)
    rank(b.id) = busStop(b.from).length
  }
  val minTime = Array.fill(m){Int.MaxValue}
  minTime(busStop(s - 1).head.id) = busStop(s - 1).head.start
  val queue = mutable.PriorityQueue()(Ordering.by[(Bus, Int), Int](_._2).reverse)
  queue.enqueue((busStop(s - 1).head, busStop(s - 1).head.start))
  while (queue.nonEmpty) {
    val (current, time) = queue.dequeue()
    if (minTime(current.id) == time) {
      if (busStop(current.from).length > rank(current.id)) {
        val next = busStop(current.from)(rank(current.id))
        if (minTime(next.id) > time + next.start - current.start) {
          minTime(next.id) = time + next.start - current.start
          queue.enqueue((next, minTime(next.id)))
        }
      }
      val i = lowerBound(busStop(current.to)){_.start >= current.reach}
      if (i < busStop(current.to).length) {
        val next = busStop(current.to)(i)
        if (minTime(next.id) > time + next.start - current.reach) {
          minTime(next.id) = time + next.start - current.reach
          queue.enqueue((next, minTime(next.id)))
        }
      }
    }
  }
  println(bus.filter(_.to == g - 1).map{bus ⇒ minTime(bus.id)}.min)
  def lowerBound[T](array: ArrayBuffer[T])(predicate: T ⇒ Boolean): Int = {
    var left = 0
    var right = array.length
    while (left < right) {
      val mid = (left + right) / 2
      if (predicate(array(mid)))  right = mid
      else left = mid + 1
    }
    right
  }
  case class Bus(id: Int, from: Int, to: Int, start: Int, reach: Int)
}
