Problem:
Score : 500 points

Problem Statement

There are N towns numbered 1 to N and M roads. The i-th road connects Town A_i and Town B_i bidirectionally and has a length of C_i.

Takahashi will travel between these towns by car, passing through these roads. The fuel tank of his car can contain at most L liters of fuel, and one liter of fuel is consumed for each unit distance traveled. When visiting a town while traveling, he can full the tank (or choose not to do so). Travel that results in the tank becoming empty halfway on the road cannot be done.

Process the following Q queries:

The tank is now full. Find the minimum number of times he needs to full his tank while traveling from Town s_i to Town t_i. If Town t_i is unreachable, print -1.

Constraints

All values in input are integers.

2 \leq N \leq 300

0 \leq M \leq \frac{N(N-1)}{2}

1 \leq L \leq 10^9

1 \leq A_i, B_i \leq N

A_i \neq B_i

\left(A_i, B_i\right) \neq \left(A_j, B_j\right) (if i \neq j)

\left(A_i, B_i\right) \neq \left(B_j, A_j\right) (if i \neq j)

1 \leq C_i \leq 10^9

1 \leq Q \leq N\left(N-1\right)

1 \leq s_i, t_i \leq N

s_i \neq t_i

\left(s_i, t_i\right) \neq \left(s_j, t_j\right) (if i \neq j)

Input

Input is given from Standard Input in the following format:

N M L
A_1 B_1 C_1
:
A_M B_M C_M
Q
s_1 t_1
:
s_Q t_Q

Output

Print Q lines.

The i-th line should contain the minimum number of times the tank needs to be fulled while traveling from Town s_i to Town t_i. If Town t_i is unreachable, the line should contain -1 instead.

Sample Input 1

3 2 5
1 2 3
2 3 3
2
3 2
1 3

Sample Output 1

0
1

To travel from Town 3 to Town 2, we can use the second road to reach Town 2 without fueling the tank on the way.

To travel from Town 1 to Town 3, we can first use the first road to get to Town 2, full the tank, and use the second road to reach Town 3.

Sample Input 2

4 0 1
1
2 1

Sample Output 2

-1

There may be no road at all.

Sample Input 3

5 4 4
1 2 2
2 3 2
3 4 3
4 5 2
20
2 1
3 1
4 1
5 1
1 2
3 2
4 2
5 2
1 3
2 3
4 3
5 3
1 4
2 4
3 4
5 4
1 5
2 5
3 5
4 5

Sample Output 3

0
0
1
2
0
0
1
2
0
0
0
1
1
1
0
0
2
2
1
0

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace ABC143E
{
    class Program
    {
        public static void Solve(Input input)
        {
            var n = input.NextInt();
            var m = input.NextInt();
            var l = input.NextInt();

            var wf = new WarshallFloyd(n);
            for (int i = 0; i < m; i++)
            {
                var a = input.NextInt() - 1;
                var b = input.NextInt() - 1;
                var c = input.NextInt();

                if (c > l)
                {
                    continue;
                }

                wf.AddPath(a, b, c);
                wf.AddPath(b, a, c);
            }

            var sp = wf.ShortestPath();

            for (int i = 0; i < n; i++)
            {
                for (int j = i + 1; j < n; j++)
                {
                    if (sp[i, j] <= l)
                    {
                        wf.AddPath(i, j, 1);
                        wf.AddPath(j, i, 1);
                    }
                }
            }

            var sp2 = wf.ShortestPath();

            var q = input.NextInt();
            for (int i = 0; i < q; i++)
            {
                var s = input.NextInt() - 1;
                var t = input.NextInt() - 1;

                if (sp2[s, t] == WarshallFloyd.Inf)
                {
                    Console.WriteLine(-1);
                    continue;
                }

                Console.WriteLine(sp2[s, t] - 1);
            }
        }

        /// <summary>
        /// 重み付き・有向グラフの全ノード間最短経路
        /// </summary>
        class WarshallFloyd
        {
            public static readonly long Inf = long.MaxValue / 3;

            // 接続情報
            readonly long[,] es;
            // ノード数
            readonly int V;

            /// <summary>
            /// 
            /// </summary>
            /// <param name="v">ノード数</param>
            public WarshallFloyd(int v)
            {
                es = new long[v, v];
                for (int i = 0; i < v; i++)
                {
                    for (int j = 0; j < v; j++)
                    {
                        es[i, j] = (i == j) ? 0 : Inf;
                    }
                }

                V = v;
            }

            /// <summary>
            /// 経路追加
            /// </summary>
            public void AddPath(int from, int to, long cost)
                => es[from, to] = cost;

            /// <summary>
            /// sから各ノードへの最短経路
            /// 負の閉路を持つ場合、nullを返す
            /// </summary>
            public long[,] ShortestPath()
            {
                var d = new long[V, V];
                for (int i = 0; i < V; i++)
                {
                    for (int j = 0; j < V; j++)
                    {
                        d[i, j] = es[i, j];
                    }
                }

                for (int i = 0; i < V; i++)
                {
                    for (int j = 0; j < V; j++)
                    {
                        for (int k = 0; k < V; k++)
                        {
                            if (d[j, i] == Inf || d[i, k] == Inf) continue;

                            d[j, k] = Math.Min(d[j, k], d[j, i] + d[i, k]);
                        }
                    }
                }

                // 負の閉路がある？
                for (int i = 0; i < V; i++)
                {
                    if (d[i, i] < 0) return null;
                }

                return d;
            }

            public List<int> Path(int s, int e, long[,] d)
            {
                var current = s;
                var path = new List<int>();
                while (current != e)
                {
                    path.Add(current);

                    for (int i = 0; i < V; i++)
                    {
                        if (i != current && es[current, i] + d[i, e] == d[current, e])
                        {
                            current = i;
                            break;
                        }
                    }
                }

                path.Add(current);

                return path;
            }
        }

        #region Main
        public static void Main(string[] args)
        {
            // 出力が少ないときはこれをセットする方が時間かかるけれど
            // そのときにTLEするのはアルゴリズムが悪いせいだし、まあ良しとする
            var needsFlushOutput = true;
            if (needsFlushOutput)
            {
                // 細かく出力しないようにする
                var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
                Console.SetOut(sw);
            }

            // 通常は引数無しで、ファイルから読み出したい場合はpath指定する
            var input = new Input();

            // 仮想的に標準入力をセットする
            // テスト入力したまま提出することがままあるので……
#if DEBUG
            input.SetText("");
#endif

            Solve(input);

            Console.Out.Flush();
        }
        #endregion

        #region Competitive Template
#pragma warning disable CS0414
        static readonly int MOD = (int)1e9 + 7;
        static readonly int[] dx = { 1, 0, -1, 0 };
        static readonly int[] dy = { 0, 1, 0, -1 };
        /// <summary> 左上が原点 </summary>
        static readonly char[] dir = { 'R', 'U', 'L', 'D' };
#pragma warning restore CS0414

        public class Input
        {
            // 変な改行コードがたまに混じっているので、一応セパレート指定する
            // スペース単独指定の方がもちろん早い
            static readonly char[] separator = { ' ', '\r', '\n' };
            readonly StreamReader sr;
            readonly Queue<string> queue;

            /// <summary>
            /// 特定のファイルから読み出したい場合はpath指定する
            /// </summary>
            public Input(string path = "")
            {
                queue = new Queue<string>();

                if (string.IsNullOrEmpty(path)) { sr = new StreamReader(Console.OpenStandardInput()); }
                else { sr = new StreamReader(path); }
            }

            /// <summary>
            /// 入力予約
            /// </summary>
            public void SetText(IEnumerable<string> items)
            {
                foreach (var item in items)
                    SetText(item);
            }

            /// <summary>
            /// 入力予約
            /// </summary>
            public bool SetText(string s)
            {
                if (string.IsNullOrEmpty(s)) return false;

                foreach (var elem in s.Trim().Split(separator, StringSplitOptions.RemoveEmptyEntries))
                    queue.Enqueue(elem);

                return true;
            }

            /// <summary>
            /// 要素が存在するか
            /// </summary>
            public bool Any() => queue.Any() || Read();

            /// <summary>
            /// 内部queueに入力からの値をsplitして格納する
            /// </summary>
            bool Read()
            {
                if (!SetText(sr.ReadLine())) return false;

                if (!queue.Any()) return Read();

                return queue.Any();
            }

            /// <summary>
            /// 次のstringを一つ読み込む
            /// </summary>
            public string Next()
            {
                if (!queue.Any() && !Read()) return "";

                return queue.Dequeue();
            }

            /// <summary>
            /// 指定個数queueにたまるまでenqueueし続ける
            /// </summary>
            bool Accumulate(int n)
            {
                while (queue.Count() < n)
                    if (!Read()) return false;

                return true;
            }

            public int NextInt() => int.Parse(Next());
            public long NextLong() => long.Parse(Next());
            public double NextDouble() => double.Parse(Next());

            /// <summary>
            /// n個の要素をparseして、それぞれにoffsetをaddした配列を返す
            /// </summary>
            T[] NextT<T>(int n, T offset, Func<string, T> parse, Func<T, T, T> add)
            {
                if (!Accumulate(n)) return null;

                var a = new T[n];

                for (int i = 0; i < n; i++)
                    a[i] = add(parse(queue.Dequeue()), offset);

                return a;
            }

            public string[] Next(int n) => NextT(n, "", x => x, (x, y) => x);
            public int[] NextInt(int n, int offset = 0) => NextT(n, offset, int.Parse, (x, y) => x + y);
            public long[] NextLong(int n, long offset = 0) => NextT(n, offset, long.Parse, (x, y) => x + y);
            public double[] NextDouble(int n, double offset = 0.0) => NextT(n, offset, double.Parse, (x, y) => x + y);
        }

        static class Utils
        {
            public static T Max<T>(params T[] objs) => objs.Max();
            public static T Min<T>(params T[] objs) => objs.Min();

            /// <summary>
            /// vでfillされたT[d1][d2]配列を作成する
            /// </summary>
            public static T[][] Create2DArray<T>(int d1, int d2, T v)
            {
                return
                    Enumerable.Repeat(0, d1).Select(_ =>
                    Enumerable.Repeat(v, d2).ToArray()).ToArray();
            }

            /// <summary>
            /// vでfillされたT[d1][d2][d3]配列を作成する
            /// </summary>
            public static T[][][] Create3DArray<T>(int d1, int d2, int d3, T v)
            {
                return
                    Enumerable.Repeat(0, d1).Select(_ =>
                    Enumerable.Repeat(0, d2).Select(__ =>
                    Enumerable.Repeat(v, d3).ToArray()).ToArray()).ToArray();
            }
        }
        #endregion
    }
}