module WeightedDirectedGraph
: sig
  (* 配列を用いたダイクストラ法の実装
     単純な速さでは一番だが，インターフェースが不便 *)
  module ByArray : sig
    module Make :
      functor (Weight : sig
        type t
        val inf : t
        val zero : t
        val ( + ) : t -> t -> t
        val compare : t -> t -> int
      end) ->
      sig
        type 'a church_list = { fold : 'b. ('a -> 'b -> 'b) -> 'b -> 'b }

        (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法
           時間計算量O(E log E)なので，疎なグラフなら速い *)
        val dijkstra :
        (* 頂点数n *)
        int ->
        (* 隣接リスト *)
        (int -> (int * Weight.t) church_list) ->
        (* 始点 *)
        int ->
        (* 始点から辿り着けなければinfを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (int -> Weight.t)

        (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法
           時間計算量O(V^2)なので，密なグラフなら速い *)
        val dijkstra_dense :
        (* 頂点数n *)
        int ->
        (* 隣接リスト *)
        (int -> (int * Weight.t) church_list) ->
        (* 始点 *)
        int ->
        (* 始点から辿り着けなければinfを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (int -> Weight.t)
      end
  end

  (* ハッシュテーブルを用いたダイクストラ法の実装
     配列を用いた実装よりは扱いやすいインターフェースを持つ
     ハッシュ関数を上手く選べば配列を用いた実装より1.5倍遅い程度ですむ *)
  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
        type 'a church_list = { fold : 'b. ('a -> 'b -> 'b) -> 'b -> 'b }

        val dijkstra :
        (* 頂点数（Hashtbl.tを用いるので目安程度） *)
        int ->
        (* 隣接リスト *)
        (Vertex.t -> (Vertex.t * Weight.t) church_list) ->
        (* 始点 *)
        Vertex.t ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      end
  end

  (* Mapを用いたダイクストラ法の実装
     配列を用いた実装より4倍ぐらい遅いが，
     一番扱いやすいインターフェースを持ち，無限グラフにも対応可能 *)
  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
        type 'a church_list = { fold : 'b. ('a -> 'b -> 'b) -> 'b -> 'b }

        val dijkstra :
        (* 隣接リスト *)
        (Vertex.t -> (Vertex.t * Weight.t) church_list) ->
        (* 始点 *)
        Vertex.t ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      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 (* 最短距離が格納されていなければNot_foundを投げる *)
      val update : t -> vertex -> W.t -> unit
    end) =
  struct
    type 'a church_list = { fold : 'b. ('a -> 'b -> 'b) -> 'b -> 'b }

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

  module ByArray = struct
    module Make (W : sig include Weight val inf : t end) = struct
      module C = Core (W) (struct
        type t = W.t array
        type vertex = int
        let find = Array.get
        let update = Array.set
      end)
      include C

      let dijkstra n e s = C.dijkstra (Array.make n W.inf) e s

      let dijkstra_dense n e s =
        let d = Array.make n W.inf in
        d.(s) <- W.zero;
        let rec dijkstra_dense_aux = function
          | [] -> ()
          | v :: vs ->
              let u, us = List.fold_left (fun (u, us) v ->
                if W.compare d.(u) d.(v) < 0
                then (u, v :: us)
                else (v, u :: us)) (v, []) vs in
              Fun.flip (e u).fold () (fun (v, c) () ->
                let open W in
                if 0 < W.compare d.(v) (d.(u) + c) then
                  d.(v) <- d.(u) + c);
              dijkstra_dense_aux us in
        dijkstra_dense_aux (List.init n Fun.id);
        Array.get d
      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
        let update = VHash.replace
      end)
      include C

      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 v !d
        let update d v w = d := VMap.add v w !d
      end)
      include C

      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 inf = max_int
  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 ->
    { G.fold = fun g acc ->
      let (v, w) = finv p in
      g (let (c, d) = vs.(v) in (f (v, min 2500 (w + c)), d)) @@
      List.fold_right (fun (u, a, b) acc ->
        if w < a
        then acc
        else g (f (u, w - a), b) acc) es.(v) acc } in
  for v = 1 to n - 1 do
    Printf.printf "%d\n" @@
    List.fold_left min max_int @@
    List.init 2501 @@ fun w ->
      try d @@ f (v, w) with Not_found -> max_int
  done


module WeightedDirectedGraph
: sig
  type 'a church_list = { fold : 'b. ('a -> 'b -> 'b) -> 'b -> 'b }

  (* 配列を用いたダイクストラ法の実装
     単純な速さでは一番だが，インターフェースが不便 *)
  module ByArray : sig
    module Make :
      functor (Weight : sig
        type t
        val inf : t
        val zero : t
        val ( + ) : t -> t -> t
        val compare : t -> t -> int
      end) ->
      sig
        (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法
           時間計算量O(E log E)なので，疎なグラフなら速い *)
        val dijkstra :
        (* 頂点数n *)
        int ->
        (* 隣接リスト *)
        (int -> (int * Weight.t) church_list) ->
        (* 始点 *)
        int ->
        (* 始点から辿り着けなければinfを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (int -> Weight.t)

        (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法
           時間計算量O(V^2)なので，密なグラフなら速い *)
        val dijkstra_dense :
        (* 頂点数n *)
        int ->
        (* 隣接リスト *)
        (int -> (int * Weight.t) church_list) ->
        (* 始点 *)
        int ->
        (* 始点から辿り着けなければinfを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (int -> Weight.t)
      end
  end

  (* ハッシュテーブルを用いたダイクストラ法の実装
     配列を用いた実装よりは扱いやすいインターフェースを持つ
     ハッシュ関数を上手く選べば配列を用いた実装より1.5倍遅い程度ですむ *)
  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) church_list) ->
        (* 始点 *)
        Vertex.t ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      end
  end

  (* Mapを用いたダイクストラ法の実装
     配列を用いた実装より4倍ぐらい遅いが，
     一番扱いやすいインターフェースを持ち，無限グラフにも対応可能 *)
  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) church_list) ->
        (* 始点 *)
        Vertex.t ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      end
  end
end
= struct
  type 'a church_list = { fold : 'b. ('a -> 'b -> 'b) -> 'b -> 'b }

  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 (* 最短距離が格納されていなければNot_foundを投げる *)
      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 WMap.min_binding !q with
        (* もう既に全ての頂点までの距離が分かっている *)
        | exception Not_found -> VArray.find d t
        | (w, us) ->
            match VArray.find d t with
            (* 既に終点までの距離が分かっているので返す *)
            | x when W.compare x w <= 0 -> x
            (* 終点までの距離が分かっていないので，ダイクストラ法を続行 *)
            | _ | exception Not_found ->
                q := WMap.remove w !q;
                Fun.flip List.iter us (fun u ->
                  if 0 <= W.compare (VArray.find d u) w then
                    (* 未だ頂点uを訪れていない *)
                    Fun.flip (e u).fold () @@ fun (v, c) () ->
                      let open W in
                      match VArray.find d v with
                      | d when W.compare d (w + c) <= 0 -> ()
                      | _ | exception Not_found ->
                          VArray.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 : sig include Weight val inf : t end) = struct
      module C = Core (W) (struct
        type t = W.t array
        type vertex = int
        let find = Array.get
        let update = Array.set
      end)

      let dijkstra n e s = C.dijkstra (Array.make n W.inf) e s

      let dijkstra_dense n e s =
        let d = Array.make n W.inf in
        d.(s) <- W.zero;
        let rec dijkstra_dense_aux = function
          | [] -> ()
          | v :: vs ->
              let u, us = List.fold_left (fun (u, us) v ->
                if W.compare d.(u) d.(v) < 0
                then (u, v :: us)
                else (v, u :: us)) (v, []) vs in
              Fun.flip (e u).fold () (fun (v, c) () ->
                let open W in
                if 0 < W.compare d.(v) (d.(u) + c) then
                  d.(v) <- d.(u) + c);
              dijkstra_dense_aux us in
        dijkstra_dense_aux (List.init n Fun.id);
        Array.get d
      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
        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 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.ByHashtbl.Make
(struct
  type t = int * int
  let equal = ( = )
  let hash (v, w) = 2501 * v + w
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 (n * 2501)) (0, min 2500 s) @@ fun (v, w) ->
    { WeightedDirectedGraph.fold = fun f acc ->
      f (let (c, d) = vs.(v) in ((v, min 2500 (w + c)), d)) @@
      List.fold_right (fun (u, a, b) acc ->
        if w < a
        then acc
        else f ((u, w - a), b) acc) es.(v) acc } in
  for v = 1 to n - 1 do
    Printf.printf "%d\n" @@
    List.fold_left min max_int @@
    List.init 2501 @@ fun w -> try d (v, w) with Not_found -> max_int
  done

Global OOD problem IDs are disjoint from train, validation, and in-distribution test problem IDs.

Score : 500 points

Problem Statement

There are N cities numbered 1 to N, connected by M railroads.

You are now at City 1, with 10^{100} gold coins and S silver coins in your pocket.

The i-th railroad connects City U_i and City V_i bidirectionally, and a one-way trip costs A_i silver coins and takes B_i minutes.
You cannot use gold coins to pay the fare.

There is an exchange counter in each city. At the exchange counter in City i, you can get C_i silver coins for 1 gold coin.
The transaction takes D_i minutes for each gold coin you give.
You can exchange any number of gold coins at each exchange counter.

For each t=2, ..., N, find the minimum time needed to travel from City 1 to City t. You can ignore the time spent waiting for trains.

Constraints

2 \leq N \leq 50

N-1 \leq M \leq 100

0 \leq S \leq 10^9

1 \leq A_i \leq 50

1 \leq B_i,C_i,D_i \leq 10^9

1 \leq U_i < V_i \leq N

There is no pair i, j(i \neq j) such that (U_i,V_i)=(U_j,V_j).

Each city t=2,...,N can be reached from City 1 with some number of railroads.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M S
U_1 V_1 A_1 B_1
:
U_M V_M A_M B_M
C_1 D_1
:
C_N D_N

Output

For each t=2, ..., N in this order, print a line containing the minimum time needed to travel from City 1 to City t.

Sample Input 1

3 2 1
1 2 1 2
1 3 2 4
1 11
1 2
2 5

Sample Output 1

2
14

The railway network in this input is shown in the figure below.

In this figure, each city is labeled as follows:

The first line: the ID number i of the city (i for City i)

The second line: C_i / D_i

Similarly, each railroad is labeled as follows:

The first line: the ID number i of the railroad (i for the i-th railroad in input)

The second line: A_i / B_i

You can travel from City 1 to City 2 in 2 minutes, as follows:

Use the 1-st railroad to move from City 1 to City 2 in 2 minutes.

You can travel from City 1 to City 3 in 14 minutes, as follows:

Use the 1-st railroad to move from City 1 to City 2 in 2 minutes.

At the exchange counter in City 2, exchange 3 gold coins for 3 silver coins in 6 minutes.

Use the 1-st railroad to move from City 2 to City 1 in 2 minutes.

Use the 2-nd railroad to move from City 1 to City 3 in 4 minutes.

Sample Input 2

4 4 1
1 2 1 5
1 3 4 4
2 4 2 2
3 4 1 1
3 1
3 1
5 2
6 4

Sample Output 2

5
5
7

The railway network in this input is shown in the figure below:

You can travel from City 1 to City 4 in 7 minutes, as follows:

At the exchange counter in City 1, exchange 2 gold coins for 6 silver coins in 2 minutes.

Use the 2-nd railroad to move from City 1 to City 3 in 4 minutes.

Use the 4-th railroad to move from City 3 to City 4 in 1 minutes.

Sample Input 3

6 5 1
1 2 1 1
1 3 2 1
2 4 5 1
3 5 11 1
1 6 50 1
1 10000
1 3000
1 700
1 100
1 1
100 1

Sample Output 3

1
9003
14606
16510
16576

The railway network in this input is shown in the figure below:

You can travel from City 1 to City 6 in 16576 minutes, as follows:

Use the 1-st railroad to move from City 1 to City 2 in 1 minute.

At the exchange counter in City 2, exchange 3 gold coins for 3 silver coins in 9000 minutes.

Use the 1-st railroad to move from City 2 to City 1 in 1 minute.

Use the 2-nd railroad to move from City 1 to City 3 in 1 minute.

At the exchange counter in City 3, exchange 8 gold coins for 8 silver coins in 5600 minutes.

Use the 2-nd railroad to move from City 3 to City 1 in 1 minute.

Use the 1-st railroad to move from City 1 to City 2 in 1 minute.

Use the 3-rd railroad to move from City 2 to City 4 in 1 minute.

At the exchange counter in City 4, exchange 19 gold coins for 19 silver coins in 1900 minutes.

Use the 3-rd railroad to move from City 4 to City 2 in 1 minute.

Use the 1-st railroad to move from City 2 to City 1 in 1 minute.

Use the 2-nd railroad to move from City 1 to City 3 in 1 minute.

Use the 4-th railroad to move from City 3 to City 5 in 1 minute.

At the exchange counter in City 5, exchange 63 gold coins for 63 silver coins in 63 minutes.

Use the 4-th railroad to move from City 5 to City 3 in 1 minute.

Use the 2-nd railroad to move from City 3 to City 1 in 1 minute.

Use the 5-th railroad to move from City 1 to City 6 in 1 minute.

Sample Input 4

4 6 1000000000
1 2 50 1
1 3 50 5
1 4 50 7
2 3 50 2
2 4 50 4
3 4 50 3
10 2
4 4
5 5
7 7

Sample Output 4

1
3
5

The railway network in this input is shown in the figure below:

Sample Input 5

2 1 0
1 2 1 1
1 1000000000
1 1

Sample Output 5

1000000001

The railway network in this input is shown in the figure below:

You can travel from City 1 to City 2 in 1000000001 minutes, as follows:

At the exchange counter in City 1, exchange 1 gold coin for 1 silver coin in 1000000000 minutes.

Use the 1-st railroad to move from City 1 to City 2 in 1 minute.

Submitted source-code file size, in bytes.

Execution CPU time reported by official Project CodeNet metadata, in milliseconds.

Peak memory usage reported by official Project CodeNet metadata, in kilobytes.


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

        (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法
           時間計算量O(V^2)なので，密なグラフなら速い *)
        val dijkstra_dense :
        (* 頂点数n *)
        int ->
        (* 隣接リスト *)
        (int -> (int * Weight.t) list) ->
        (* 始点 *)
        int ->
        (* 始点から辿り着けなければinfを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (int -> Weight.t)
      end
  end

  (* ハッシュテーブルを用いたダイクストラ法の実装
     配列を用いた実装よりは扱いやすいインターフェースを持つ
     ハッシュ関数を上手く選べば配列を用いた実装より1.5倍遅い程度ですむ *)
  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 ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      end
  end

  (* Mapを用いたダイクストラ法の実装
     配列を用いた実装より4倍ぐらい遅いが，
     一番扱いやすいインターフェースを持ち，無限グラフにも対応可能 *)
  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 ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      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 (* 最短距離が格納されていなければNot_foundを投げる *)
      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 WMap.min_binding !q with
        (* もう既に全ての頂点までの距離が分かっている *)
        | exception Not_found -> VArray.find d t
        | (w, us) ->
            match VArray.find d t with
            (* 既に終点までの距離が分かっているので返す *)
            | x when W.compare x w <= 0 -> x
            (* 終点までの距離が分かっていないので，ダイクストラ法を続行 *)
            | _ | exception Not_found ->
                q := WMap.remove w !q;
                List.iter (fun u ->
                  if 0 <= W.compare (VArray.find d u) w then
                    (* 未だ頂点uを訪れていない *)
                    List.iter (fun (v, c) ->
                      let open W in
                      match VArray.find d v with
                      | d when W.compare d (w + c) <= 0 -> ()
                      | _ | exception Not_found ->
                          VArray.update d v (w + c);
                          q := WMap.update (w + c) (fun vs -> Some (v :: Option.value ~default:[] vs)) !q) (e u)) us;
                dijkstra_aux t in
      dijkstra_aux
  end

  module ByArray = struct
    module Make (W : sig include Weight val inf : t end) = struct
      module C = Core (W) (struct
        type t = W.t array
        type vertex = int
        let find = Array.get
        let update = Array.set
      end)

      let dijkstra n e s = C.dijkstra (Array.make n W.inf) e s

      let dijkstra_dense n e s =
        let d = Array.make n W.inf in
        d.(s) <- W.zero;
        let rec dijkstra_dense_aux = function
          | [] -> ()
          | v :: vs ->
              let u, us = List.fold_left (fun (u, us) v ->
                if W.compare d.(u) d.(v) < 0
                then (u, v :: us)
                else (v, u :: us)) (v, []) vs in
              List.iter (fun (v, c) ->
                let open W in
                if 0 < W.compare d.(v) (d.(u) + c) then
                  d.(v) <- d.(u) + c) (e u);
              dijkstra_dense_aux us in
        dijkstra_dense_aux (List.init n Fun.id);
        Array.get d
      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
        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 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.ByHashtbl.Make
(struct
  type t = int * int
  let equal = ( = )
  let hash (v, w) = 2501 * v + w
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 (n * 2501)) (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 -> try d (v, w) with Not_found -> max_int
  done


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

        (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法
           時間計算量O(V^2)なので，密なグラフなら速い *)
        val dijkstra_dense :
        (* 頂点数n *)
        int ->
        (* 隣接リスト *)
        (int -> (int * Weight.t) list) ->
        (* 始点 *)
        int ->
        (* 始点から辿り着けなければinfを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (int -> Weight.t)
      end
  end

  (* ハッシュテーブルを用いたダイクストラ法の実装
     配列を用いた実装よりは扱いやすいインターフェースを持つ
     ハッシュ関数を上手く選べば配列を用いた実装より1.5倍遅い程度ですむ *)
  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 ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      end
  end

  (* Mapを用いたダイクストラ法の実装
     配列を用いた実装より4倍ぐらい遅いが，
     一番扱いやすいインターフェースを持ち，無限グラフにも対応可能 *)
  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 ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      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 (* 最短距離が格納されていなければNot_foundを投げる *)
      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 WMap.min_binding_opt !q with
        (* もう既に全ての頂点までの距離が分かっている *)
        | None -> VArray.find d t
        | Some (w, us) ->
            match VArray.find d t with
            (* 既に終点までの距離が分かっているので返す *)
            | x when W.compare x w <= 0 -> x
            (* 終点までの距離が分かっていないので，ダイクストラ法を続行 *)
            | _ | exception Not_found ->
                q := WMap.remove w !q;
                List.iter (fun u ->
                  if 0 <= W.compare (VArray.find d u) w then
                    (* 未だ頂点uを訪れていない *)
                    List.iter (fun (v, c) ->
                      let open W in
                      match VArray.find d v with
                      | d when W.compare d (w + c) <= 0 -> ()
                      | _ | exception Not_found ->
                          VArray.update d v (w + c);
                          q := WMap.update (w + c) (fun vs -> Some (v :: Option.value ~default:[] vs)) !q) (e u)) us;
                dijkstra_aux t in
      dijkstra_aux
  end

  module ByArray = struct
    module Make (W : sig include Weight val inf : t end) = struct
      module C = Core (W) (struct
        type t = W.t array
        type vertex = int
        let find = Array.get
        let update = Array.set
      end)

      let dijkstra n e s = C.dijkstra (Array.make n W.inf) e s

      let dijkstra_dense n e s =
        let d = Array.make n W.inf in
        d.(s) <- W.zero;
        let rec dijkstra_dense_aux = function
          | [] -> ()
          | v :: vs ->
              let u, us = List.fold_left (fun (u, us) v ->
                if W.compare d.(u) d.(v) < 0
                then (u, v :: us)
                else (v, u :: us)) (v, []) vs in
              List.iter (fun (v, c) ->
                let open W in
                if 0 < W.compare d.(v) (d.(u) + c) then
                  d.(v) <- d.(u) + c) (e u);
              dijkstra_dense_aux us in
        dijkstra_dense_aux (List.init n Fun.id);
        Array.get d
      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
        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 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.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 -> try d (v, w) with Not_found -> max_int
  done


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

        (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法
           時間計算量O(V^2)なので，密なグラフなら速い *)
        val dijkstra_dense :
        (* 頂点数n *)
        int ->
        (* 隣接リスト *)
        (int -> (int * Weight.t) list) ->
        (* 始点 *)
        int ->
        (* 始点から辿り着けなければinfを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (int -> Weight.t)
      end
  end

  (* ハッシュテーブルを用いたダイクストラ法の実装
     配列を用いた実装よりは扱いやすいインターフェースを持つ
     ハッシュ関数を上手く選べば配列を用いた実装より1.5倍遅い程度ですむ *)
  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 ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      end
  end

  (* Mapを用いたダイクストラ法の実装
     配列を用いた実装より4倍ぐらい遅いが，
     一番扱いやすいインターフェースを持ち，無限グラフにも対応可能 *)
  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 ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      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 (* 最短距離が格納されていなければNot_foundを投げる *)
      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 WMap.min_binding_opt !q with
        (* もう既に全ての頂点までの距離が分かっている *)
        | None -> VArray.find d t
        | Some (w, us) ->
            match VArray.find d t with
            (* 既に終点までの距離が分かっているので返す *)
            | x when W.compare x w <= 0 -> x
            (* 終点までの距離が分かっていないので，ダイクストラ法を続行 *)
            | _ | exception Not_found ->
                q := WMap.remove w !q;
                List.iter (fun u ->
                  if 0 <= W.compare (VArray.find d u) w then
                    (* 未だ頂点uを訪れていない *)
                    List.iter (fun (v, c) ->
                      let open W in
                      match VArray.find d v with
                      | d when W.compare d (w + c) <= 0 -> ()
                      | _ | exception Not_found ->
                          VArray.update d v (w + c);
                          q := WMap.update (w + c) (fun vs -> Some (v :: Option.value ~default:[] vs)) !q) (e u)) us;
                dijkstra_aux t in
      dijkstra_aux
  end

  module ByArray = struct
    module Make (W : sig include Weight val inf : t end) = struct
      module C = Core (W) (struct
        type t = W.t array
        type vertex = int
        let find = Array.get
        let update = Array.set
      end)

      let dijkstra n e s = C.dijkstra (Array.make n W.inf) e s

      let dijkstra_dense n e s =
        let d = Array.make n W.inf in
        d.(s) <- W.zero;
        let rec dijkstra_dense_aux = function
          | [] -> ()
          | v :: vs ->
              let u, us = List.fold_left (fun (u, us) v ->
                if W.compare d.(u) d.(v) < 0
                then (u, v :: us)
                else (v, u :: us)) (v, []) vs in
              List.iter (fun (v, c) ->
                let open W in
                if 0 < W.compare d.(v) (d.(u) + c) then
                  d.(v) <- d.(u) + c) (e u);
              dijkstra_dense_aux us in
        dijkstra_dense_aux (List.init n Fun.id);
        Array.get d
      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
        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 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.ByHashtbl.Make
(struct
  type t = int * int
  let equal = ( = )
  let hash (v, w) = 2501 * v + w
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 (n * 2501)) (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 -> try d (v, w) with Not_found -> max_int
  done


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

        (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法
           時間計算量O(V^2)なので，密なグラフなら速い *)
        val dijkstra_dense :
        (* 頂点数n *)
        int ->
        (* 隣接リスト *)
        (int -> (int * Weight.t) list) ->
        (* 始点 *)
        int ->
        (* 始点から辿り着けなければinfを返す関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (int -> Weight.t)
      end
  end

  (* ハッシュテーブルを用いたダイクストラ法の実装
     配列を用いた実装よりは扱いやすいインターフェースを持つ
     ハッシュ関数を上手く選べば配列を用いた実装より1.5倍遅い程度ですむ *)
  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 ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      end
  end

  (* Mapを用いたダイクストラ法の実装
     配列を用いた実装より4倍ぐらい遅いが，
     一番扱いやすいインターフェースを持ち，無限グラフにも対応可能 *)
  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 ->
        (* 始点から辿り着けなければNot_foundを投げる関数
           この関数を覚えておけば，呼び出しごとの途中までの計算結果がシェアされる *)
        (Vertex.t -> Weight.t)
      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 (* 最短距離が格納されていなければNot_foundを投げる *)
      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 WMap.min_binding_opt !q with
        (* もう既に全ての頂点までの距離が分かっている *)
        | None -> VArray.find d t
        | Some (w, us) ->
            match VArray.find d t with
            (* 既に終点までの距離が分かっているので返す *)
            | x when W.compare x w <= 0 -> x
            (* 終点までの距離が分かっていないので，ダイクストラ法を続行 *)
            | _ | exception Not_found ->
                q := WMap.remove w !q;
                List.iter (fun u ->
                  if 0 <= W.compare (VArray.find d u) w then
                    (* 未だ頂点uを訪れていない *)
                    List.iter (fun (v, c) ->
                      let open W in
                      match VArray.find d v with
                      | d when W.compare d (w + c) <= 0 -> ()
                      | _ | exception Not_found ->
                          VArray.update d v (w + c);
                          q := WMap.update (w + c) (fun vs -> Some (v :: Option.value ~default:[] vs)) !q) (e u)) us;
                dijkstra_aux t in
      dijkstra_aux
  end

  module ByArray = struct
    module Make (W : sig include Weight val inf : t end) = struct
      module C = Core (W) (struct
        type t = W.t array
        type vertex = int
        let find = Array.get
        let update = Array.set
      end)

      let dijkstra n e s = C.dijkstra (Array.make n W.inf) e s

      let dijkstra_dense n e s =
        let d = Array.make n W.inf in
        d.(s) <- W.zero;
        let rec dijkstra_dense_aux = function
          | [] -> ()
          | v :: vs ->
              let u, us = List.fold_left (fun (u, us) v ->
                if W.compare d.(u) d.(v) < 0
                then (u, v :: us)
                else (v, u :: us)) (v, []) vs in
              List.iter (fun (v, c) ->
                let open W in
                if 0 < W.compare d.(v) (d.(u) + c) then
                  d.(v) <- d.(u) + c) (e u);
              dijkstra_dense_aux us in
        dijkstra_dense_aux (List.init n Fun.id);
        Array.get d
      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
        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 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 inf = 12345678901234
  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 ->
      try d @@ f (v, w) with Not_found -> max_int
  done


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


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.ByHashtbl.Make
(struct
  type t = int * int
  let equal = ( = )
  let hash (v, w) = 2501 * v + w
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 (n * 2501)) (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


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.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


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


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
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
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


module WeightedDirectedGraph
  (* 頂点 *)
  (Vertex : Hashtbl.HashedType)
  (* 辺の重み *)
  (Weight : sig
    type t
    val zero : t
    val ( + ) : t -> t -> t
    val compare : t -> t -> int
  end) :
sig
  (* ハッシュテーブルを使うようにしたダイクストラ法の実装 *)
  val dijkstra :
    (* 頂点数（Hashtblを用いるので目安程度） *)
    int ->
    (* 隣接リスト *)
    (Vertex.t -> (Vertex.t * Weight.t) list) ->
    (* 始点 *)
    Vertex.t ->
    (* 始点から辿り着けなければNoneを返す関数 *)
    (Vertex.t -> Weight.t option)
end =
struct
  module WMap = Map.Make (Weight)
  module VHash = Hashtbl.Make (Vertex)

  let dijkstra n es s =
    let d = VHash.create n in
    VHash.add d s Weight.zero;
    let rec dijkstra_aux q =
      match WMap.min_binding_opt q with
      | None -> ()
      | Some (w, us) ->
          dijkstra_aux @@
          Fun.flip (Fun.flip List.fold_left (WMap.remove w q)) us @@ fun q u ->
            if 0 < Weight.compare w (VHash.find d u)
            then q
            else Fun.flip (Fun.flip List.fold_left q) (es u) @@ fun q (v, c) ->
              let open Weight in
              match VHash.find_opt d v with
              | Some d when Weight.compare d (w + c) <= 0 -> q
              | _ ->
                  VHash.replace d v (w + c);
                  WMap.add (w + c) (v :: try WMap.find (w + c) q with Not_found -> []) q in
    dijkstra_aux (WMap.singleton Weight.zero [s]);
    VHash.find_opt d
end

module G = WeightedDirectedGraph
(struct
  type t = int * int
  let equal = ( = )
  let hash (v, w) = 2501 * v + w
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 (n * 2501)) (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


module WeightedDirectedGraph
  (* 辺の重み *)
  (Weight : sig
    type t
    val zero : t
    val ( + ) : t -> t -> t
    val compare : t -> t -> int
  end) :
sig
  (* ハッシュテーブルを使うようにしたダイクストラ法の実装 *)
  val raw_dijkstra :
    (* 頂点数（Hashtblを用いるので目安程度） *)
    int ->
    (* 隣接リスト *)
    ('v -> ('v * Weight.t) list) ->
    (* 始点 *)
    'v ->
    (* 始点から辿り着けなければNoneを返す関数 *)
    ('v -> Weight.t option)
end =
struct
  module WMap = Map.Make (Weight)

  let raw_dijkstra n es s =
    let d = Hashtbl.create n in
    Hashtbl.add d s Weight.zero;
    let rec dijkstra_aux q =
      match WMap.min_binding_opt q with
      | None -> ()
      | Some (w, us) ->
          dijkstra_aux @@
          Fun.flip (Fun.flip List.fold_left (WMap.remove w q)) us @@ fun q u ->
            if 0 < Weight.compare w (Hashtbl.find d u)
            then q
            else Fun.flip (Fun.flip List.fold_left q) (es u) @@ fun q (v, c) ->
              let open Weight in
              match Hashtbl.find_opt d v with
              | Some d when Weight.compare d (w + c) <= 0 -> q
              | _ ->
                  Hashtbl.replace d v (w + c);
                  WMap.add (w + c) (v :: try WMap.find (w + c) q with Not_found -> []) q in
    dijkstra_aux (WMap.singleton Weight.zero [s]);
    Hashtbl.find_opt d
end

module G = WeightedDirectedGraph (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.raw_dijkstra (n * 2501)) (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


module WeightedDirectedGraph
  (* 辺の重み *)
  (Weight : sig
    type t
    val inf : t (* max_intとかを突っ込むとオーバーフローで死ぬので気をつけること *)
    val zero : t
    val ( + ) : t -> t -> t
    val compare : t -> t -> int
  end) :
sig
  (* 頂点を[0, n)の自然数に限定したグラフに対してのダイクストラ法 *)
  val raw_dijkstra :
    (* 頂点数 *)
    int ->
    (* 隣接リスト *)
    (int -> (int * Weight.t) list) ->
    (* 始点 *)
    int ->
    (* 始点から辿り着けなければWeight.infを返す関数 *)
    (int -> Weight.t)
end =
struct
  module WMap = Map.Make (Weight)

  let raw_dijkstra n es s =
    let d = Array.make n Weight.inf in
    d.(s) <- Weight.zero;
    let rec dijkstra_aux q =
      match WMap.min_binding_opt q with
      | None -> ()
      | Some (w, us) ->
          dijkstra_aux @@
          ListLabels.fold_left ~init:(WMap.remove w q) us ~f:(fun q u ->
            if 0 < Weight.compare w d.(u)
            then q
            else ListLabels.fold_left ~init:q (es u) ~f:(fun q (v, c) ->
              let open Weight in
              if Weight.compare d.(v) (w + c) <= 0
              then q
              else begin
                d.(v) <- w + c;
                WMap.add (w + c) (v :: try WMap.find (w + c) q with Not_found -> []) q
              end)) in
    dijkstra_aux (WMap.singleton Weight.zero [s]);
    Array.get d
end

module G = WeightedDirectedGraph (struct
  type t = int
  let zero = 0
  let ( + ) = ( + )
  let compare = compare
  let inf = 12345678901234
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.raw_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 -> d (f (v, w))
  done


module WeightedDirectedGraph
  (Vertex : sig
    type t
    val compare : t -> t -> int
  end)
  (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 =
struct
  module WMap = Map.Make (Weight)
  module VMap = Map.Make (Vertex)

  let dijkstra e s =
    (* 始点sからの距離 *)
    (* d に入っていない頂点への距離は無限大とみなす *)
    let d = ref @@ VMap.singleton s Weight.zero in
    (* 優先度付きキュー *)
    let q = ref @@ WMap.singleton Weight.zero [s] in
    (* ダイクストラ法のメインループ *)
    let rec dijkstra_aux t =
      match VMap.find_opt t !d, WMap.min_binding_opt !q with
      (* もう既に全ての頂点までの距離が分かっている *)
      | ans, None -> ans
      (* 既に終点までの距離が分かっているので返す *)
      | Some x as ans, Some (w, _) when Weight.compare x w <= 0 -> ans
      (* 終点までの距離が分かっていないので，ダイクストラ法を続行 *)
      | _, Some (w, us) ->
          q := WMap.remove w !q;
          Fun.flip List.iter us (fun u ->
            if 0 <= Weight.compare (VMap.find u !d) w then
              (* 未だ頂点uを訪れていない *)
              Fun.flip List.iter (e u) (fun (v, c) ->
                let open Weight in
                match VMap.find_opt v !d with
                | Some d when Weight.compare d (w + c) <= 0 -> ()
                | _ ->
                    d := VMap.add v (w + c) !d;
                    q := WMap.add (w + c) (v :: try WMap.find (w + c) !q with Not_found -> []) !q));
          dijkstra_aux t in dijkstra_aux
end

module G = WeightedDirectedGraph
  (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_matrix n 2501 [] in
  for i = 0 to m - 1 do
    Scanf.scanf "%d %d %d %d\n" @@ fun u v a b ->
      for i = a to 2500 do
        es.(u - 1).(i) <- ((v - 1, i - a), b) :: es.(u - 1).(i);
        es.(v - 1).(i) <- ((u - 1, i - a), b) :: es.(v - 1).(i);
      done
  done;
  for v = 0 to n - 1 do
    Scanf.scanf "%d %d\n" @@ fun c d ->
      for j = 0 to 2500 do
        es.(v).(j) <- ((v, min 2500 (j + c)), d) :: es.(v).(j)
      done
  done;
  let d = Fun.flip G.dijkstra (0, min 2500 s) @@ fun (v, c) -> es.(v).(c) in
  for v = 1 to n - 1 do
    Printf.printf "%d\n" @@
    List.fold_left min max_int @@
    List.init 2501 @@ fun i ->
      Option.value ~default:max_int @@ d (v, i)
  done


module WeightedDirectedGraph
  (Vertex : sig
    type t
    val compare : t -> t -> int
  end)
  (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 =
struct
  module WMap = Map.Make (Weight)
  module VMap = Map.Make (Vertex)

  let dijkstra e s =
    (* 始点sからの距離 *)
    (* d に入っていない頂点への距離は無限大とみなす *)
    let d = ref @@ VMap.singleton s Weight.zero in
    (* 優先度付きキュー *)
    let q = ref @@ WMap.singleton Weight.zero [s] in
    (* ダイクストラ法のメインループ *)
    let rec dijkstra_aux t =
      match VMap.find_opt t !d, WMap.min_binding_opt !q with
      (* もう既に全ての頂点までの距離が分かっている *)
      | ans, None -> ans
      (* 既に終点までの距離が分かっているので返す *)
      | Some x as ans, Some (w, _) when Weight.compare x w <= 0 -> ans
      (* 終点までの距離が分かっていないので，ダイクストラ法を続行 *)
      | _, Some (w, us) ->
          q := WMap.remove w !q;
          Fun.flip List.iter us (fun u ->
            if 0 <= Weight.compare (VMap.find u !d) w then
              (* 未だ頂点uを訪れていない *)
              Fun.flip List.iter (e u) (fun (v, c) ->
                let open Weight in
                match VMap.find_opt v !d with
                | Some d when Weight.compare d (w + c) <= 0 -> ()
                | _ ->
                    d := VMap.add v (w + c) !d;
                    q := WMap.add (w + c) (v :: try WMap.find (w + c) !q with Not_found -> []) !q));
          dijkstra_aux t in dijkstra_aux
end

module G = WeightedDirectedGraph
  (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_matrix n 3001 [] in
  for i = 0 to m - 1 do
    Scanf.scanf "%d %d %d %d\n" @@ fun u v a b ->
      for i = a to 3000 do
        es.(u - 1).(i) <- ((v - 1, i - a), b) :: es.(u - 1).(i);
        es.(v - 1).(i) <- ((u - 1, i - a), b) :: es.(v - 1).(i);
      done
  done;
  for v = 0 to n - 1 do
    Scanf.scanf "%d %d\n" @@ fun c d ->
      for j = 0 to 3000 do
        es.(v).(j) <- ((v, min 3000 (j + c)), d) :: es.(v).(j)
      done
  done;
  let d = Fun.flip G.dijkstra (0, min 3000 s) @@ fun (v, c) -> es.(v).(c) in
  for v = 1 to n - 1 do
    Printf.printf "%d\n" @@
    List.fold_left min max_int @@
    List.init 3001 @@ fun i ->
      Option.value ~default:max_int @@ d (v, i)
  done


module IntMap = Map.Make (struct
  type t = int
  let compare = compare
end)

let () = Scanf.scanf "%d %d %d\n" @@ fun n m s ->
  let es = Array.make_matrix n 2501 [] in
  for i = 0 to m - 1 do
    Scanf.scanf "%d %d %d %d\n" @@ fun u v a b ->
      for i = a to 2500 do
        es.(u - 1).(i) <- ((v - 1, i - a), b) :: es.(u - 1).(i);
        es.(v - 1).(i) <- ((u - 1, i - a), b) :: es.(v - 1).(i);
      done
  done;
  for v = 0 to n - 1 do
    Scanf.scanf "%d %d\n" @@ fun c d ->
      for j = 0 to 2500 do
        es.(v).(j) <- ((v, min 2500 (j + c)), d) :: es.(v).(j)
      done
  done;
  let d = Array.make_matrix n 2501 1234567890123 in
  d.(0).(min 2500 s) <- 0;
  let rec dijkstra q =
    match IntMap.min_binding q with
    | exception Not_found -> ()
    | (w, us) ->
        dijkstra @@ List.fold_left (fun q (u, u') ->
          if d.(u).(u') < w
          then q
          else List.fold_left (fun q ((v, v'), c) ->
            if compare d.(v).(v') (w + c) <= 0
            then q
            else begin
              d.(v).(v') <- w + c;
              IntMap.add (w + c) ((v, v') :: try IntMap.find (w + c) q with Not_found -> []) q
  end) q es.(u).(u')) (IntMap.remove w q) us in
  dijkstra (IntMap.singleton 0 [(0, min 2500 s)]);
  for i = 1 to n - 1 do
    Printf.printf "%d\n" @@ Array.fold_left min max_int d.(i)
  done


let pi = atan 1. *. 4. in
let r = read_float() in
print_float (2. *. pi *. r)

Score : 100 points

Problem Statement

Print the circumference of a circle of radius R.

Constraints

1 \leq R \leq 100

All values in input are integers.

Input

Input is given from Standard Input in the following format:

R

Output

Print the circumference of the circle.
Your output is considered correct if and only if its absolute or relative error from our answer is at most 10^{-2}.

Sample Input 1

1

Sample Output 1

6.28318530717958623200

Since we accept an absolute or relative error of at most 10^{-2}, 6.28 is also an acceptable output, but 6 is not.

Sample Input 2

73

Sample Output 2

458.67252742410977361942


let circle_pond r =
  let pi = 4.0 *. atan 1.0 in
    (float r) *. 2.0 *. pi

let () = Printf.printf "%f\n" @@ circle_pond (read_int ())


let pi = atan 1. *. 4.
let r = Scanf.sscanf (read_line ()) "%f" @@ fun r -> r

let () = Printf.printf "%f\n" @@ r *. 2. *. pi


let r = read_float ()
let () = print_float (2. *. r *. 3.141)


open Printf
open Scanf

let solve r =
  let pi = 4.0 *. atan 1.0 in
  2.0 *. pi *. float_of_int r

let () =
  scanf "%d " solve |> printf "%f\n"


let rec lucky7 n =
  if n mod 10 = 7 then "Yes"
  else if n / 10 = 0 then "No"
  else lucky7 (n / 10)

let () = print_endline (lucky7 (read_int()))

Score : 100 points

Problem Statement

Given is a three-digit integer N. Does N contain the digit 7?

If so, print Yes; otherwise, print No.

Constraints

100 \leq N \leq 999

Input

Input is given from Standard Input in the following format:

N

Output

If N contains the digit 7, print Yes; otherwise, print No.

Sample Input 1

117

Sample Output 1

Yes

117 contains 7 as its last digit.

Sample Input 2

123

Sample Output 2

No

123 does not contain the digit 7.

Sample Input 3

777

Sample Output 3

Yes


let n = read_line ()

let () = print_endline @@
  if String.length (Str.global_replace (Str.regexp "7") "" n) = 3 then "No" else "Yes"


open Batteries
module EnumL = Enum.Labels
module ListL = List.Labels
module ArrayL = Array.Labels

let dbg0 x = Printf.eprintf "[debug]%s\n" @@ dump x
let dbg1 x = dbg0 x; x

let id = identity

let (++) n m = List.range n `To m
let (++-) n m = if n >= m then List.range n `Downto m else []
let (++^) n m = if n < m then List.range n `To (pred m) else []

module ModOp = struct
  let prime = 1_000_000_007
  let (-) a b = (a + prime - b) mod prime
  let (+) a b = (a + b) mod prime
  let ( * ) a b = (a * b) mod prime

  let rec pow x n =
    if n = 0 then 1
    else if n mod 2 = 0 then pow (x*x) (n/2)
    else x * pow (x*x) (n/2)
end

let scan fmt = Scanf.sscanf (read_line ()) fmt

let scan_lines n fmt f =
  if n = 0 then []
  else List.map (fun _ -> scan fmt f) (1 ++ n)

let scan_list ?sep cnv =
  let line = read_line () in
  (match sep with
   | None -> List.map String.of_char @@ String.to_list line
   | Some sep -> String.split_on_char sep line)
  |> List.map cnv

let scan_array ?sep cnv = Array.of_list @@ scan_list ?sep cnv

let scan_matrix n m e ?sep conv =
  let arr = Array.make_matrix n m e in
  ListL.iter (0 ++^ n)
    ~f:(fun i -> arr.(i) <- Array.of_list @@ scan_list ?sep conv);
  arr

let atoi c = Char.code c - Char.code '0'

let rec powerset = function
  | [] -> [[]]
  | hd::tl ->
    let pws =  powerset tl in
    pws @ ListL.map pws ~f:(fun pw -> hd::pw)

let permutations l =
  let rec interleave x = function
    | [] -> [[x]]
    | (hd::tl) as l ->
      (x::l) :: (interleave x tl |> ListL.map ~f:(fun l -> hd::l)) in
  let rec aux = function
    | [] -> [[]]
    | a::rest ->
      aux rest |> ListL.map ~f:(interleave a) |> List.concat in
  aux l

let intersection l =
  EnumL.filter ~f:(fun x -> EnumL.exists ~f:((=) x) @@ Enum.clone l)

let zip l m =
  let n = min (List.length l) (List.length m) in
  List.combine (List.take n l) (List.take n m)

let lower_bound n f =
  let rec aux l u =
    if u - l > 1 then
      let m = (l + u) / 2 in
      if f m then aux l m
      else aux m u
    else u in aux (-1) n

let between n x m = n <= x && x < m

let n = scan "%s" id

let () =
  if String.contains n '7' then
    Printf.printf "Yes\n"
  else Printf.printf "No\n"


open Batteries
module EnumL = Enum.Labels
module ListL = List.Labels
module ArrayL = Array.Labels

let dbg0 x = Printf.eprintf "[debug]%s\n" @@ dump x
let dbg1 x = dbg0 x; x

let id = identity

let (++) n m = List.range n `To m
let (++-) n m = if n >= m then List.range n `Downto m else []
let (++^) n m = if n < m then List.range n `To (pred m) else []

module ModOp = struct
  let prime = 1_000_000_007
  let (-) a b = (a + prime - b) mod prime
  let (+) a b = (a + b) mod prime
  let ( * ) a b = (a * b) mod prime

  let rec pow x n =
    if n = 0 then 1
    else if n mod 2 = 0 then pow (x*x) (n/2)
    else x * pow (x*x) (n/2)
end

let scan fmt = Scanf.sscanf (read_line ()) fmt

let scan_lines n fmt f =
  if n = 0 then []
  else List.map (fun _ -> scan fmt f) (1 ++ n)

let scan_list ?sep cnv =
  let line = read_line () in
  (match sep with
   | None -> List.map String.of_char @@ String.to_list line
   | Some sep -> String.split_on_char sep line)
  |> List.map cnv

let scan_array ?sep cnv = Array.of_list @@ scan_list ?sep cnv

let scan_matrix n m e ?sep conv =
  let arr = Array.make_matrix n m e in
  ListL.iter (0 ++^ n)
    ~f:(fun i -> arr.(i) <- Array.of_list @@ scan_list ?sep conv);
  arr

let atoi c = Char.code c - Char.code '0'

let rec powerset = function
  | [] -> [[]]
  | hd::tl ->
    let pws =  powerset tl in
    pws @ ListL.map pws ~f:(fun pw -> hd::pw)

let permutations l =
  let rec interleave x = function
    | [] -> [[x]]
    | (hd::tl) as l ->
      (x::l) :: (interleave x tl |> ListL.map ~f:(fun l -> hd::l)) in
  let rec aux = function
    | [] -> [[]]
    | a::rest ->
      aux rest |> ListL.map ~f:(interleave a) |> List.concat in
  aux l

let intersection l =
  EnumL.filter ~f:(fun x -> EnumL.exists ~f:((=) x) @@ Enum.clone l)

let zip l m =
  let n = min (List.length l) (List.length m) in
  List.combine (List.take n l) (List.take n m)

let lower_bound n f =
  let rec aux l u =
    if u - l > 1 then
      let m = (l + u) / 2 in
      if f m then aux l m
      else aux m u
    else u in aux (-1) n

let between n x m = n <= x && x < m

let n = scan "%s" id

let () =
  if String.contains n '7' then
    Printf.printf "Yes\n"
  else Printf.printf "NO\n"


let () = print_endline @@
  let s = read_line () in
  match String.index_opt s '7'  with
      Some (x) -> "Yes"
    | None -> "No"


let n = read_int ()
let ans =
  if n / 100 = 7 || n mod 10 = 7 || (n mod 100 - n mod 10) = 70
  then "Yes" else "No"
let () = print_endline ans


let () = Scanf.scanf "%d" @@ fun n ->
  print_endline @@
  if n mod 10 = 7 || n / 10 mod 10 = 7 || n / 100 mod 10 = 7
  then "Yes"
  else "No"


let s = read_line ();;
let a =
	if s.[0] == '7' then 1 else 0;;
let b =
	if s.[1] == '7' then 1 else 0;;
let c =
	if s.[2] == '7' then 1 else 0;;
if a + b + c > 0 then print_string ("Yes") else print_string ("No");;


let s = read_line ();;
let a =
	if s.[0] == '7' then 1 else 0;;
let b =
	if s.[1] == '7' then 1 else 0;;
let c =
	if s.[2] == '7' then 1 else 0;;
print_int (a+b+c)


Scanf.scanf "%d" (fun s ->
    print_endline @@ if s mod 10 = 7 || (s / 10) mod 10 = 7 || (s / 100) mod 10 = 7 then "Yes" else "No")


open Batteries
(* 文字列をcharのlistにする *)
let explode s = List.init (String.length s) (String.get s)
let n = read_line() |> explode
let _ = (if List.mem '7' n then "Yes" else "No") |> print_endline


open Batteries
module EnumL = Enum.Labels
module ListL = List.Labels
module ArrayL = Array.Labels

let dbg0 x = Printf.eprintf "[debug]%s\n" @@ dump x
let dbg1 x = dbg0 x; x

let id = identity

let (++) n m = List.range n `To m
let (++-) n m = if n >= m then List.range n `Downto m else []
let (++^) n m = if n < m then List.range n `To (pred m) else []

module ModOp = struct
  let prime = 1_000_000_007
  let (-) a b = (a + prime - b) mod prime
  let (+) a b = (a + b) mod prime
  let ( * ) a b = (a * b) mod prime

  let rec pow x n =
    if n = 0 then 1
    else if n mod 2 = 0 then pow (x*x) (n/2)
    else x * pow (x*x) (n/2)
end

let scan fmt = Scanf.sscanf (read_line ()) fmt

let scan_lines n fmt f =
  if n = 0 then []
  else List.map (fun _ -> scan fmt f) (1 ++ n)

let scan_list ?sep cnv =
  let line = read_line () in
  (match sep with
   | None -> List.map String.of_char @@ String.to_list line
   | Some sep -> String.split_on_char sep line)
  |> List.map cnv

let scan_array ?sep cnv = Array.of_list @@ scan_list ?sep cnv

let scan_matrix n m e ?sep conv =
  let arr = Array.make_matrix n m e in
  ListL.iter (0 ++^ n)
    ~f:(fun i -> arr.(i) <- Array.of_list @@ scan_list ?sep conv);
  arr

let atoi c = Char.code c - Char.code '0'

let rec powerset = function
  | [] -> [[]]
  | hd::tl ->
    let pws =  powerset tl in
    pws @ ListL.map pws ~f:(fun pw -> hd::pw)

let permutations l =
  let rec interleave x = function
    | [] -> [[x]]
    | (hd::tl) as l ->
      (x::l) :: (interleave x tl |> ListL.map ~f:(fun l -> hd::l)) in
  let rec aux = function
    | [] -> [[]]
    | a::rest ->
      aux rest |> ListL.map ~f:(interleave a) |> List.concat in
  aux l

let intersection l =
  EnumL.filter ~f:(fun x -> EnumL.exists ~f:((=) x) @@ Enum.clone l)

let zip l m =
  let n = min (List.length l) (List.length m) in
  List.combine (List.take n l) (List.take n m)

let lower_bound n f =
  let rec aux l u =
    if u - l > 1 then
      let m = (l + u) / 2 in
      if f m then aux l m
      else aux m u
    else u in aux (-1) n

let between n x m = n <= x && x < m

let k = scan "%d" id

let rec gcd  a b =
  if b = 0 then a
  else gcd b (a mod b)

let () =
  let memo = Array.make_matrix (succ k) (succ k) 0 in
  ListL.iter (1++k) ~f:(fun i ->
      ListL.iter (1++k) ~f:(fun j ->
          memo.(i).(j) <- gcd i j
        )
    );
  ListL.map (1++k) ~f:(fun i ->
      ListL.map (1++k) ~f:(fun j ->
          ListL.map (1++k) ~f:(fun m ->
              memo.(memo.(i).(j)).(m)
            ) |> List.sum
        ) |> List.sum
    )|>List.sum
  |> Printf.printf "%d\n"

Score : 300 points

Problem Statement

Find \displaystyle{\sum_{a=1}^{K}\sum_{b=1}^{K}\sum_{c=1}^{K} \gcd(a,b,c)}.

Here \gcd(a,b,c) denotes the greatest common divisor of a, b, and c.

Constraints

1 \leq K \leq 200

K is an integer.

Input

Input is given from Standard Input in the following format:

K

Output

Print the value of \displaystyle{\sum_{a=1}^{K}\sum_{b=1}^{K}\sum_{c=1}^{K} \gcd(a,b,c)}.

Sample Input 1

2

Sample Output 1

9

\gcd(1,1,1)+\gcd(1,1,2)+\gcd(1,2,1)+\gcd(1,2,2)
+\gcd(2,1,1)+\gcd(2,1,2)+\gcd(2,2,1)+\gcd(2,2,2)
=1+1+1+1+1+1+1+2=9

Thus, the answer is 9.

Sample Input 2

200

Sample Output 2

10813692


let rec gcd a b = if b = 0 then a else gcd b (a mod b)
let ans = ref 0;;
let () =
  Scanf.scanf "%d\n" @@ fun k ->
  for i = k downto 1 do
    for j = k downto 1 do
      for l = k downto 1 do
        ans := (gcd i (gcd j l)) + !ans
      done
    done
  done;
  Printf.printf "%d\n" !ans


let rec gcd n m =
  if m = 0 then n
  else gcd m (n mod m)

let () = Scanf.scanf "%d" @@ fun k ->
  Printf.printf "%d\n" @@
  Array.fold_left (Array.fold_left (Array.fold_left ( + ))) 0 @@
  Array.init k @@ fun a ->
    Array.init k @@ fun b ->
      Array.init k @@ fun c ->
        gcd (a + 1) (gcd (b + 1) (c + 1))


open Printf
open Scanf

let rec gcd a b =
  if b = 0 then a
  else gcd b (a mod b)

let solve n =
  let rec loop i j k sm =
    if i > n then sm
    else if j > n then loop (i + 1) 1 1 sm
    else if k > n then loop i (j + 1) 1 sm
    else loop i j (k + 1) (sm + gcd i (gcd j k)) in
  loop 1 1 1 0

let () =
  scanf "%d " solve |> printf "%d\n"


Scanf.scanf "%d" (fun k ->
    let mat = Array.make_matrix 201 201 (-1) in
    let rec gcd a b = if b = 0 then a else
        if mat.(a).(b) >= 0 then mat.(a).(b) else
            let r = gcd b (a mod b) in
            let () = mat.(a).(b) <- r in
            r
    in

    let rec loop_a a acc =
        let rec loop_b b acc =
            let rec loop_c ab c acc =
                if c > k then acc else loop_c ab (c + 1) (acc + gcd ab c)
            in
            if b > k then acc else loop_b (b + 1) (loop_c (gcd a b) 1 acc)
        in
        if a > k then acc else loop_a (a + 1) (loop_b 1 acc)
    in
    loop_a 1 0 |> Printf.printf "%d\n"
)