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)
    (* グラフの頂点を添字とした配列 *)
    (VArray : 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 =
      VArray.update d s W.zero;
      let q = ref (WMap.singleton W.zero [s]) in
      let rec dijkstra_aux t =
        match VArray.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 (VArray.find d u)) w then
                (* 未だ頂点uを訪れていない *)
                Fun.flip List.iter (e u) @@ fun (v, c) ->
                  let open W in
                  match VArray.find d v with
                  | Some d when W.compare d (w + c) <= 0 -> ()
                  | _ ->
                      VArray.update d v (w + c);
                      q := Fun.flip (WMap.update (w + c)) !q @@
                             fun vs -> Some (v :: Option.value ~default:[] vs));
            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 = C.dijkstra (Array.make n None) 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 = C.dijkstra (VHash.create n) 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.empty) e s
    end
  end
end

module G = WeightedDirectedGraph.ByArray.Make
(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 f (v, w) = n * w + v in
  let finv x = (x mod n, x / n) in
  let d = Fun.flip (G.dijkstra (n * 2501)) (f (0, min 2500 s)) @@ fun p ->
    let (v, w) = finv p in
    (let (c, d) = vs.(v) in (f (v, min 2500 (w + c)), d)) ::
      Fun.flip List.filter_map es.(v) (fun (u, a, b) ->
        if w < a
        then None
        else Some (f (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 @@ f (v, w)
  done
