import scala.collection.mutable

object Main extends App {

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

  val Array(n, m, s, g) = readLine.trim.split(' ').map(_.toInt)
  val edges = Array.tabulate(n){_ ⇒ Nil: List[(Int, Edge)]}
  for (_ ← 0 until m){
    val Array(u, v, a, b) = readLine.trim.split(' ').map(_.toLong)
    val edge = Edge(a, b)
    edges(u.toInt - 1) ::= (v.toInt - 1, edge)
    edges(v.toInt - 1) ::= (u.toInt - 1, edge)
  }
  val minTime = Array.tabulate(n){ _ ⇒ Long.MaxValue}.also{ arr ⇒ arr(s - 1) = 0l}
  val queue = mutable.PriorityQueue()(Ordering.by[(Int, Long), Long](_._2).reverse).also{que ⇒ que.enqueue((s - 1, 0l))}
  while (queue.nonEmpty){
    val (top, current) = queue.dequeue()
    if (minTime(top) == current){
      for ((next, edge) ← edges(top)){
        if (edge.minTime >= current){
          val near = List(edge.minTime.ceil.toLong, edge.minTime.floor.toLong).map{t ⇒ t + edge.costAt(t)}.min
          if (minTime(next) > near) {
            minTime(next) = near
            queue.enqueue((next, near))
          }
        }else if (minTime(next) > edge.costAt(current) + current){
          minTime(next) = edge.costAt(current) + current
          queue.enqueue((next, minTime(next)))
        }
      }
    }
  }
  println(if (minTime(g - 1) == Long.MaxValue) -1 else minTime(g - 1))
  case class Edge(private val a: Long, private val b: Long) {
    def costAt(time: Double): Long = math.ceil(b / (time + a)).toLong
    def minTime: Double = {
      val time = math.sqrt(b) - a
      if (time >= 0) time
      else 0d
    }
  }
  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)
  }
}
