module WeightedDirectedGraph
: sig
  (* 配列を用いたダイクストラ法の実装 *)
  module ByArray : sig
    module Make :
      functor (Weight : sig
        type t
        val zero : t
        val ( + ) : t -> t -> t
        val compare : t -> t -> int
      end) ->
      sig
        (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法 *)
        val dijkstra : 
        (* 頂点数 *)
        int ->
        (* 隣接リスト *)
        (int -> (int * Weight.t) list) ->
        (* 始点 *)
        int ->
        (* 始点から辿り着けなければNoneを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (int -> Weight.t option)
      end
  end

  (* ハッシュテーブルを用いたダイクストラ法の実装 *)
  module ByHashtbl : sig
    module Make :
      functor 
      (* 頂点 *)
      (Vertex : Hashtbl.HashedType)
      (* 辺の重み *)
      (Weight : sig
        type t
        val zero : t
        val ( + ) : t -> t -> t
        val compare : t -> t -> int
      end) ->
      sig
        val dijkstra : 
        (* 頂点数（Hashtbl.tを用いるので目安程度） *)
        int ->
        (* 隣接リスト *)
        (Vertex.t -> (Vertex.t * Weight.t) list) ->
        (* 始点 *)
        Vertex.t ->
        (* 始点から辿り着けなければNoneを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t option)
      end
  end

  (* Mapを用いたダイクストラ法の実装
     無限グラフにも対応可能 *)
  module ByMap : sig
    module Make :
      functor 
      (* 頂点 *)
      (Vertex : Map.OrderedType)
      (* 辺の重み *)
      (Weight : sig
        type t
        val zero : t
        val ( + ) : t -> t -> t
        val compare : t -> t -> int
      end) ->
      sig
        val dijkstra : 
        (* 隣接リスト *)
        (Vertex.t -> (Vertex.t * Weight.t) list) ->
        (* 始点 *)
        Vertex.t ->
        (* 始点から辿り着けなければNoneを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t option)
      end
  end
end
= struct
  module type Weight = sig
    type t
    val zero : t
    val ( + ) : t -> t -> t
    val compare : t -> t -> int
  end

  (* ダイクストラ法のメインループ *)
  module Core
    (W : Weight)
    (* Imperative map *)
    (VMap : sig
      type t
      type vertex
      val find : t -> vertex -> W.t option
      val update : t -> vertex -> W.t -> unit
    end) =
  struct
    module WMap = Map.Make (W)

    let dijkstra d e s =
      let q = ref (WMap.singleton W.zero [s]) in
      let rec dijkstra_aux t =
        match VMap.find d t, WMap.min_binding_opt !q with
        (* もう既に全ての頂点までの距離が分かっている *)
        | ans, None -> ans
        (* 既に終点までの距離が分かっているので返す *)
        | Some x as ans, Some (w, _) when W.compare x w <= 0 -> ans
        (* 終点までの距離が分かっていないので，ダイクストラ法を続行 *)
        | _, Some (w, us) ->
            q := WMap.remove w !q;
            Fun.flip List.iter us (fun u ->
              if 0 <= W.compare (Option.get (VMap.find d u)) w then
                (* 未だ頂点uを訪れていない *)
                Fun.flip List.iter (e u) @@ fun (v, c) ->
                  let open W in
                  match VMap.find d v with
                  | Some d when W.compare d (w + c) <= 0 -> ()
                  | _ ->
                      VMap.update d v (w + c);
                      q := WMap.update (w + c) (fun vs -> Some (v :: Option.value ~default:[] vs)) !q);
            dijkstra_aux t in
      dijkstra_aux
  end

  module ByArray = struct
    module Make (W : Weight) = struct
      module C = Core (W) (struct
        type t = W.t option array
        type vertex = int
        let find = Array.get 
        let update d v w = d.(v) <- Some w
      end)

      let dijkstra n e s =
        let d = Array.make n None in
        d.(s) <- Some W.zero;
        C.dijkstra d e s
    end
  end

  module ByHashtbl = struct
    module Make (V : Hashtbl.HashedType) (W : Weight) = struct
      module VHash = Hashtbl.Make (V)
      module C = Core (W) (struct
        type t = W.t VHash.t
        type vertex = V.t
        let find = VHash.find_opt
        let update = VHash.replace
      end)

      let dijkstra n e s =
        let d = VHash.create n in
        VHash.add d s W.zero;
        C.dijkstra d e s
    end
  end

  module ByMap = struct
    module Make (V : Map.OrderedType) (W : Weight) = struct
      module VMap = Map.Make (V)
      module C = Core (W) (struct
        type t = W.t VMap.t ref
        type vertex = V.t
        let find d v = VMap.find_opt v !d
        let update d v w = d := VMap.add v w !d
      end)

      let dijkstra e s = C.dijkstra (ref (VMap.singleton s W.zero)) e s
    end
  end
end

module G = WeightedDirectedGraph.ByMap.Make
(struct
  type t = int * int
  let compare = compare
end)
(struct
  type t = int
  let zero = 0
  let ( + ) = ( + )
  let compare = compare
end)

let () = Scanf.scanf "%d %d %d\n" @@ fun n m s ->
  let es = Array.make n [] in
  for i = 0 to m - 1 do
    Scanf.scanf "%d %d %d %d\n" @@ fun u v a b ->
      es.(u - 1) <- (v - 1, a, b) :: es.(u - 1);
      es.(v - 1) <- (u - 1, a, b) :: es.(v - 1);
  done;
  let vs = Array.init n @@ fun _ -> Scanf.scanf "%d %d\n" @@ fun c d -> (c, d) in
  let d = Fun.flip G.dijkstra (0, min 2500 s) @@ fun (v, w) ->
    (let (c, d) = vs.(v) in ((v, min 2500 (w + c)), d)) ::
      Fun.flip List.filter_map es.(v) (fun (u, a, b) ->
        if w < a
        then None
        else Some ((u, w - a), b)) in
  for v = 1 to n - 1 do
    Printf.printf "%d\n" @@
    List.fold_left min max_int @@
    List.init 2501 @@ fun w -> Option.value ~default:max_int @@ d (v, w)
  done


Measured memory_bytes: 33956