#include <bits/stdc++.h>
using namespace std;

#define FOR(i, a, b) for(int i=(a);i<(b);++i)
#define REP(i, n)  for(int i=0;i<(n);++i)
#define REPr(i, n) for(int i=(n)-1;i>=0; --i)
#define FORq(i, m, n) for(int i = (m);i <= (n);++i)
#define FORqr(i, m, n) for(int i = (n);i >=(m);--i)
#define PB push_back
#define MP make_pair
#define fst first
#define snd second
#define SIN(x, S) (S.count(x) != 0)
#define M0(x) memset(x,0,sizeof(x))
#define FILL(x, y) memset(x,y,sizeof(x))
#define MM(x) memset(x,-1,sizeof(x))
#define ALL(x) (x).begin(),(x).end()
#define DB(x) cerr << #x << " = " << x << endl
#define DB2(x, y) cerr << "(" << #x << ", " << #y << ") = (" << x << ", " << y << ")\n";
#define DEBUG int x12345; cin >> x12345;
typedef pair<int, int> PII;
typedef pair<long long, long long> PLL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<long long> VL;
typedef long long ll;
typedef long long integer;
///////////////////////////////////////////////
const ll MOD = 1e9 + 7;
 
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
 
template<class T>
inline bool chmin(T &a, T b) {
	if (a > b) {
		a = b;
		return true;
	}
	return false;
}
 
template<class T>
inline bool chmax(T &a, T b) {
	if (a < b) {
		a = b;
		return true;
	}
	return false;
}
 
template<int MOD>
struct Fp {
	long long val;
 
	constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
		if (val < 0) v += MOD;
	}
 
	constexpr int getmod() { return MOD; }
 
	constexpr Fp operator-() const noexcept {
		return val ? MOD - val : 0;
	}
 
	constexpr Fp operator+(const Fp &r) const noexcept { return Fp(*this) += r; }
 
	constexpr Fp operator-(const Fp &r) const noexcept { return Fp(*this) -= r; }
 
	constexpr Fp operator*(const Fp &r) const noexcept { return Fp(*this) *= r; }
 
	constexpr Fp operator/(const Fp &r) const noexcept { return Fp(*this) /= r; }
 
	constexpr Fp &operator+=(const Fp &r) noexcept {
		val += r.val;
		if (val >= MOD) val -= MOD;
		return *this;
	}
 
	constexpr Fp &operator-=(const Fp &r) noexcept {
		val -= r.val;
		if (val < 0) val += MOD;
		return *this;
	}
 
	constexpr Fp &operator*=(const Fp &r) noexcept {
		val = val * r.val % MOD;
		return *this;
	}
 
	constexpr Fp &operator/=(const Fp &r) noexcept {
		long long a = r.val, b = MOD, u = 1, v = 0;
		while (b) {
			long long t = a / b;
			a -= t * b;
			swap(a, b);
			u -= t * v;
			swap(u, v);
		}
		val = val * u % MOD;
		if (val < 0) val += MOD;
		return *this;
	}
 
	constexpr bool operator==(const Fp &r) const noexcept {
		return this->val == r.val;
	}
 
	constexpr bool operator!=(const Fp &r) const noexcept {
		return this->val != r.val;
	}
 
	friend constexpr ostream &operator<<(ostream &os, const Fp<MOD> &x) noexcept {
		return os << x.val;
	}
 
	friend constexpr istream &operator>>(istream &is, Fp<MOD> &x) noexcept {
		return is >> x.val;
	}
 
	friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
		if (n == 0) return 1;
		auto t = modpow(a, n / 2);
		t = t * t;
		if (n & 1) t = t * a;
		return t;
	}
};
 
using mint = Fp<MOD>;
 
void scdvec(vector<int> &a, int n, int s = 0) {
	for (int i = s; i < n; ++i) { scanf("%d", &a[i]); }
}
 
void sclldvec(vector<long long> &a, int n, int s = 0) {
	for (int i = s; i < n; ++i) { scanf("%lld", &a[i]); }
}
 
///////////////////////////////////////////////
///  ((((っ・ω・)っ |AC|
struct Vertex {
	// edge information
	vector<int> edges_to; //to vertex number
	vector<ll> edges_cost; // edge cost
	
	//for dijkstra
	bool done; //conform or not
	ll cost; // now cost
	ll supply;
	int from;
	
	bool operator<(const Vertex& another) const { // priority --> min
        bool C = false;
		if (another.supply < supply) C = true;
		if ((another.supply == supply) and (another.cost < cost)){
			C = true;
		}
		return C;
    }
	
	bool operator==(const Vertex& another) const {
        return (another.supply == supply) and 
		(another.cost == cost);
    }
};

int main() {
	int N,M,L;
	scanf("%d%d%d", &N, &M, &L);
	vector<Vertex> V(N+5);
	REP(i,M){
		int A,B,C;
		scanf("%d%d%d", &A, &B, &C);		
		V[A].edges_to.PB(B);
		V[A].edges_cost.PB(C);
		V[B].edges_to.PB(A);
		V[B].edges_cost.PB(C);
	}

	static ll ans[302][302] = {};
	FORq(i,1,300){
		FORq(j,1,300){
			ans[i][j] = -1;
		}
	}

	FORq(s,1,N){
		FORq(i,1,N){
			V[i].cost = 0;
			V[i].supply = 100000;
			V[i].done = false;
		}

		V[s].done = false;
		V[s].supply = 0;
		int donenum = 1;
		while(donenum < N){
			int now = -1;
			PLL M = MP(1000000,0);
			FORq(i,1,N){
				if (V[i].done) continue;
				if (MP(V[i].supply,V[i].cost) < M){
					now = i;
					M = MP(V[i].supply,V[i].cost);
				}
			}

			DB(now);

			V[now].done = true;
			donenum++;

			REP(i,V[now].edges_cost.size()){
				int next = V[now].edges_to[i];
				if (V[next].done) continue;
				ll ncost,nsupply;
				if (V[now].edges_cost[i] > L) continue;
				nsupply = V[now].supply;
				ncost = V[now].cost + V[now].edges_cost[i];
				if (ncost > L){
					ncost =  V[now].edges_cost[i];
					nsupply++;
				}

				if ((V[next].cost == 0) and (V[next].supply == 100000)){
					V[next].supply = nsupply;
					V[next].cost = ncost;
				}
				
				if (MP(V[next].supply,V[next].cost) > MP(nsupply,ncost)){
					V[next].supply = nsupply;
					V[next].cost = ncost;
				}
			}
		}

		FORq(i,1,N){
			if ((V[i].supply == 100000)) continue;
			ans[s][i] = V[i].supply;
		}
	}

	int Q; scanf("%d",&Q);
	REP(q,Q){
		int s,t;
		scanf("%d%d", &s, &t);
		printf("%lld\n",ans[s][t]);
	}
}



Measured memory_bytes: 3072