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.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using Debug = System.Diagnostics.Trace;
using SB = System.Text.StringBuilder;
using System.Numerics;
using static System.Math;
using Number = System.Int32;

namespace Program {
	public class Solver {
		Random rnd = new Random();
		public void Solve() {
			var n = ri;
			var m = ri;
			var L = rl;
			var g = Enumerate(n, x => new long[n]);
			var h = Enumerate(n, x => new long[n]);
			for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) g[i][j] = g[j][i] = h[i][j] = h[j][i] = INF;
			for (int i = 0; i < m; i++) {
				var u = ri - 1;
				var v = ri - 1;
				var w = ri;
				g[u][v] = g[v][u] = w;
			}
			for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++)
						g[i][j] = Min(g[i][j], g[i][k] + g[k][j]);
			for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) {
					if (g[i][j] <= L) h[i][j] = h[j][i] = 1;
				}
			for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++)
						h[i][j] = Min(h[i][j], h[i][k] + h[k][j]);
			var q = ri;
			for (int i = 0; i < q; i++) {
				var u = ri - 1;
				var v = ri - 1;
				var ans = h[u][v] - 1;
				if (ans >= 1000000000) ans = -1;
				Console.WriteLine(ans);
			}
		}
		const long INF = 1L << 60;
		static int[] dx = { -1, 0, 1, 0 };
		static int[] dy = { 0, 1, 0, -1 };
		int ri { get { return sc.Integer(); } }
		long rl { get { return sc.Long(); } }
		double rd { get { return sc.Double(); } }
		string rs { get { return sc.Scan(); } }
		public IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());

		static T[] Enumerate<T>(int n, Func<int, T> f) {
			var a = new T[n];
			for (int i = 0; i < a.Length; ++i) a[i] = f(i);
			return a;
		}
		static public void Swap<T>(ref T a, ref T b) { var tmp = a; a = b; b = tmp; }
	}
}

#region main
static class Ex {
	static public string AsString(this IEnumerable<char> ie) { return new string(ie.ToArray()); }
	static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") {
		return string.Join(st, ie);
	}
	static public void Main() {
		Console.SetOut(new Program.IO.Printer(Console.OpenStandardOutput()) { AutoFlush = true });
		var solver = new Program.Solver();
		/* 
		var t = new System.Threading.Thread(solver.Solve, 50000000);
		t.Start();
		t.Join();
		//*/
		solver.Solve();
		Console.Out.Flush();
	}
}
#endregion
#region Ex
namespace Program.IO {
	using System.IO;
	using System.Text;
	using System.Globalization;

	public class Printer : StreamWriter {
		public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
		public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
	}

	public class StreamScanner {
		public StreamScanner(Stream stream) { str = stream; }

		public readonly Stream str;
		private readonly byte[] buf = new byte[1024];
		private int len, ptr;
		public bool isEof = false;
		public bool IsEndOfStream { get { return isEof; } }

		private byte read() {
			if (isEof) return 0;
			if (ptr >= len) {
				ptr = 0;
				if ((len = str.Read(buf, 0, 1024)) <= 0) {
					isEof = true;
					return 0;
				}
			}
			return buf[ptr++];
		}

		public char Char() {
			byte b = 0;
			do b = read(); while ((b < 33 || 126 < b) && !isEof);
			return (char)b;
		}
		public string Scan() {
			var sb = new StringBuilder();
			for (var b = Char(); b >= 33 && b <= 126; b = (char)read()) sb.Append(b);
			return sb.ToString();
		}
		public string ScanLine() {
			var sb = new StringBuilder();
			for (var b = Char(); b != '\n' && b != 0; b = (char)read()) if (b != '\r') sb.Append(b);
			return sb.ToString();
		}
		public long Long() { return isEof ? long.MinValue : long.Parse(Scan()); }
		public int Integer() { return isEof ? int.MinValue : int.Parse(Scan()); }
		public double Double() { return isEof ? double.NaN : double.Parse(Scan(), CultureInfo.InvariantCulture); }
	}
}

#endregion

#region ModInt
/// <summary>
/// [0,<see cref="Mod"/>) までの値を取るような数
/// </summary>
public struct ModInt {
	/// <summary>
	/// 剰余を取る値．
	/// </summary>
	public const long Mod = (int)1e9 + 7;

	/// <summary>
	/// 実際の数値．
	/// </summary>
	public long num;
	/// <summary>
	/// 値が <paramref name="n"/> であるようなインスタンスを構築します．
	/// </summary>
	/// <param name="n">インスタンスが持つ値</param>
	/// <remarks>パフォーマンスの問題上，コンストラクタ内では剰余を取りません．そのため，<paramref name="n"/> ∈ [0,<see cref="Mod"/>) を満たすような <paramref name="n"/> を渡してください．このコンストラクタは O(1) で実行されます．</remarks>
	public ModInt(long n) { num = n; }
	/// <summary>
	/// このインスタンスの数値を文字列に変換します．
	/// </summary>
	/// <returns>[0,<see cref="Mod"/>) の範囲内の整数を 10 進表記したもの．</returns>
	public override string ToString() { return num.ToString(); }
	public static ModInt operator +(ModInt l, ModInt r) { l.num += r.num; if (l.num >= Mod) l.num -= Mod; return l; }
	public static ModInt operator -(ModInt l, ModInt r) { l.num -= r.num; if (l.num < 0) l.num += Mod; return l; }
	public static ModInt operator *(ModInt l, ModInt r) { return new ModInt(l.num * r.num % Mod); }
	public static implicit operator ModInt(long n) { n %= Mod; if (n < 0) n += Mod; return new ModInt(n); }

	/// <summary>
	/// 与えられた 2 つの数値からべき剰余を計算します．
	/// </summary>
	/// <param name="v">べき乗の底</param>
	/// <param name="k">べき指数</param>
	/// <returns>繰り返し二乗法により O(N log N) で実行されます．</returns>
	public static ModInt Pow(ModInt v, long k) { return Pow(v.num, k); }

	/// <summary>
	/// 与えられた 2 つの数値からべき剰余を計算します．
	/// </summary>
	/// <param name="v">べき乗の底</param>
	/// <param name="k">べき指数</param>
	/// <returns>繰り返し二乗法により O(N log N) で実行されます．</returns>
	public static ModInt Pow(long v, long k) {
		long ret = 1;
		for (k %= Mod - 1; k > 0; k >>= 1, v = v * v % Mod)
			if ((k & 1) == 1) ret = ret * v % Mod;
		return new ModInt(ret);
	}
	/// <summary>
	/// 与えられた数の逆元を計算します．
	/// </summary>
	/// <param name="v">逆元を取る対象となる数</param>
	/// <returns>逆元となるような値</returns>
	/// <remarks>法が素数であることを仮定して，フェルマーの小定理に従って逆元を O(log N) で計算します．</remarks>
	public static ModInt Inverse(ModInt v) { return Pow(v, Mod - 2); }
}
#endregion
#region Binomial Coefficient
public class BinomialCoefficient {
	public ModInt[] fact, ifact;
	public BinomialCoefficient(int n) {
		fact = new ModInt[n + 1];
		ifact = new ModInt[n + 1];
		fact[0] = 1;
		for (int i = 1; i <= n; i++)
			fact[i] = fact[i - 1] * i;
		ifact[n] = ModInt.Inverse(fact[n]);
		for (int i = n - 1; i >= 0; i--)
			ifact[i] = ifact[i + 1] * (i + 1);
		ifact[0] = ifact[1];
	}
	public ModInt this[int n, int r] {
		get {
			if (n < 0 || n >= fact.Length || r < 0 || r > n) return 0;
			return fact[n] * ifact[n - r] * ifact[r];
		}
	}
	public ModInt RepeatedCombination(int n, int k) {
		if (k == 0) return 1;
		return this[n + k - 1, k];
	}
}
#endregion

#region BinarySearch
public static partial class Algorithm {
	static int binarySearch<T>(IList<T> a, T v, IComparer<T> cmp, bool islb) {
		var l = 0;
		var r = a.Count - 1;
		while (l <= r) {
			var m = (l + r) / 2;
			var res = cmp.Compare(a[m], v);
			if (res < 0 || (res == 0 && !islb)) l = m + 1;
			else r = m - 1;
		}
		return l;
	}

	/// <summary>
	/// 与えられた比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> 以上の要素であるような最小のインデックスを取得します．
	/// </summary>
	/// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
	/// <param name="a">対象となるコレクション</param>
	/// <param name="v">対象となる要素</param>
	/// <param name="f"></param>
	/// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
	/// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
	public static int LowerBound<T>(this IList<T> a, T v, Comparison<T> f) { return binarySearch(a, v, Comparer<T>.Create(f), true); }

	/// <summary>
	///　デフォルトの比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> 以上の要素であるような最小のインデックスを取得します．
	/// </summary>
	/// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
	/// <param name="a">対象となるコレクション</param>
	/// <param name="v">対象となる要素</param>
	/// <param name="f"></param>
	/// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
	/// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
	public static int LowerBound<T>(this IList<T> a, T v) { return binarySearch(a, v, Comparer<T>.Default, true); }

	/// <summary>
	/// 与えられた比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> 以上の要素であるような最小のインデックスを取得します．
	/// </summary>
	/// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
	/// <param name="a">対象となるコレクション</param>
	/// <param name="v">対象となる要素</param>
	/// <param name="f"></param>
	/// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
	/// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
	public static int UpperBound<T>(this IList<T> a, T v, Comparison<T> cmp) { return binarySearch(a, v, Comparer<T>.Create(cmp), false); }

	/// <summary>
	///　デフォルトの比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> より真に大きい要素が現れる最小のインデックスを取得します．
	/// </summary>
	/// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
	/// <param name="a">対象となるコレクション</param>
	/// <param name="v">対象となる要素</param>
	/// <param name="f"></param>
	/// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
	/// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
	public static int UpperBound<T>(this IList<T> a, T v) { return binarySearch(a, v, Comparer<T>.Default, false); }

}
#endregion