#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <functional>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#include <set>
#define nmax_def 110000
#define Cmax_def 2200
#define mod 1000000007
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
#define graph_from1 true
#define graph_tree false
#define graph_weight true
#define graph_digraph false

class Graph_func
{
public:
	int Vnum;
	int Enum;
	int L;
	vector<pair<int, int> > edgelist;
	vector<ll> edgeweight;
	vector<vector<int> > adjlist;
	vector<vector<ll> > adjlistweight;
	vector<int> adjnum;

	vector<pll> xdist;

	vector<bool> x_visited;
	vector<int> x_prqarr;
	vector<bool> x_filled;

	void read_edge();
	void adjini();
	void visited_ini();
	void adjsort();
	vector<bool> graph_num_BFS(int BFS_ini, vector<bool> filled);
	int graph_num();
	void graph_BFS(ll BFS_ini);
	void graph_DFS(ll DFS_ini);
	void xydist_fill(int x, ll dist_tmp);
	void xydist_tree(int x, ll dist_tmp);   // ex. xydist_tree(3, 0)
	void xydist(int x);   // ex. xydist(3, 0)
	ll diameter();
	int leaves_num();

	bool xydist_def = false;
};

void Graph_func::read_edge()
{
	cin >> Vnum;
	if (graph_tree)
		Enum = Vnum - 1;// graph
	else
		cin >> Enum;
	cin >> L;
	edgelist.resize(Enum);
	edgeweight.resize(Enum);
	adjnum.resize(Vnum);
	xdist.resize(Vnum);
	adjlist.resize(Vnum);
	if (graph_weight)
		adjlistweight.resize(Vnum);
	for (int i = 0; i < Enum; i++)
	{
		if (graph_weight)
			cin >> edgelist[i].first >> edgelist[i].second >> edgeweight[i];
		else
			cin >> edgelist[i].first >> edgelist[i].second;
		if (graph_from1)
		{
			edgelist[i].first--;
			edgelist[i].second--;
		}
	}
	return;
}

void Graph_func::adjini()
{
	for (int i = 0; i < Vnum; i++)
		adjnum[i] = 0;
	int Enum_new = 0;
	for (int i = 0; i < Enum; i++)
	{
		if (edgeweight[i] > L)
			continue;
		int x = edgelist[i].first;
		int y = edgelist[i].second;
		adjlist[x].push_back(y);
		if (!graph_digraph)
			adjlist[y].push_back(x);
		if (graph_weight)
		{
			ll xyweight = edgeweight[i];
			adjlistweight[x].push_back(xyweight);
			if (!graph_digraph)
				adjlistweight[y].push_back(xyweight);
		}
		adjnum[x]++;
		if (!graph_digraph)
			adjnum[y]++;
		Enum_new++;
	}
	Enum = Enum_new;
	x_visited.resize(Vnum);
	for (int i = 0; i < Vnum; i++)
		x_visited[i] = false;

	return;
}


void Graph_func::xydist(int x)  // ex. xydist(3), Dijkstra's algorithm
{
	priority_queue<pair<pll, int>, vector<pair<pll, int> >, greater<pair<pll, int> > > xdist_que; //Alive_vertices
	ll max_tmp = pow(10, 18) * 4;
	for (int i = 0; i < Vnum; i++)
		xdist[i] = pll(max_tmp, max_tmp);
	xdist[x] = pll(0, 0);
	pair<pll, int> xdist_que_tmp;
	xdist_que_tmp.first = pll(0, 0);
	xdist_que_tmp.second = x;
	xdist_que.push(xdist_que_tmp);
	while (!xdist_que.empty())
	{
		xdist_que_tmp = xdist_que.top();
		xdist_que.pop();
		pll xdist_tmp = xdist_que_tmp.first;
		int x_tmp = xdist_que_tmp.second;
		if (xdist[x_tmp] == xdist_tmp)
		{
			for (int i = 0; i < adjnum[x_tmp]; i++)
			{
				int x_new = adjlist[x_tmp][i];
				ll dist_diff;
				dist_diff = adjlistweight[x_tmp][i];
				pll xdist_new = xdist[x_tmp];
				xdist_new.second += dist_diff;
				if (xdist_new.second > L)
				{
					xdist_new.first++;
					xdist_new.second = dist_diff; // 給油
				}
				if (xdist[x_new].first > xdist_new.first || (xdist[x_new].first == xdist_new.first && xdist[x_new].second > xdist_new.second))
				{
					xdist[x_new] = xdist_new;
					xdist_que_tmp.first = xdist[x_new];
					xdist_que_tmp.second = x_new;
					xdist_que.push(xdist_que_tmp);
				}
			}
		}
	}
}

int main(void)
{
	Graph_func graph;
	graph.read_edge();
	graph.adjini();
	ll Vnum = graph.Vnum;
	ll Enum = graph.Enum;
	vector<vector<pll>> ans;
	ans.resize(Vnum);
	rep(i, Vnum) {
		graph.xydist(i);
		ans[i] = graph.xdist;
	}
	int Q;
	cin >> Q;
	rep(i, Q) {
		int s, t;
		cin >> s >> t;
		ll ansans = ans[s-1][t-1].first;
		if (ansans >= pow(10, 9))
			ansans = -1;
		cout << ansans << endl;
	}
	return 0;
}

Measured memory_bytes: 4480