#include <bits/stdc++.h>

using u32 = uint32_t;
using u64 = uint64_t;
using i32 = int32_t;
using i64 = int64_t;

constexpr u64 INF = std::numeric_limits<u64>::max();

struct V
{
	explicit V(u64 idx, u64 n)
	  : id(idx)
	{
		adj.reserve(n);
	}

	u64 id;
	std::vector<std::pair<u64,u64>> adj;

	void print()
	{
		std::clog << "V(id=" << id 
				  << ") adj: ";
		for(u64 i=0; i<adj.size(); i++)
		{
			std::clog << adj[i].first << "(" << adj[i].second << "), ";
		}
		std::clog << "\n";
	}

	void reset()
	{
	}
};

struct G
{
	explicit G(u64 n)
	{
		v.reserve(n);
		for(u64 i=0; i<n; i++)
		{
			v.push_back(V{i+1, n});
		}
	}

	V& vtx(u64 idx)
	{
		return v[idx-1];
	}

	void EdgeUW(u64 a, u64 b, u64 w)
	{
		vtx(a).adj.emplace_back(b,w);
		vtx(b).adj.emplace_back(a,w);
	}
	
	void print()
	{
		for(u64 i=0;i<v.size();i++)
		{
			v[i].print();
		}
	}

	void reset()
	{
		for(u64 i=0;i<v.size();i++)
		{
			v[i].reset();
		}
	}

	std::vector<V> v;
};

struct cmpElems
{
	cmpElems(const std::vector<u64>& tanks, const std::vector<i64>& fuel)
	  : _tanks(tanks), _fuel(fuel)
	{}
	const std::vector<u64>& _tanks;
	const std::vector<i64>& _fuel;
};

struct cmp
{
	cmp(const cmpElems& params)
	  : _tanks(params._tanks), _fuel(params._fuel)
	{}

	bool operator()(const u64& a, const u64& b)
	{
		//std::clog << "cmp(" << a << "," << b << ") : _tanks[a] = " << _tanks[a] << " _tanks[b] = " << _tanks[b] << " _fuel[a] = " << _fuel[a] << " _fuel[b] = " << _fuel[b] << "\n";
		if(_tanks[a] == _tanks[b])
		{
			if(_fuel[a] == _fuel[b])
			{
				return a<b;
			}
			return _fuel[a] > _fuel[b];
		}
		return _tanks[a] < _tanks[b];
	}
private:
	const std::vector<u64>& _tanks;
	const std::vector<i64>& _fuel;
};

std::vector<u64> Dijkstra(const u64 n, G& g, const u64 src, const u64 l)
{
	std::vector<u64> tanks(n+1, INF);
	std::vector<i64> fuel(n+1, 0);

	std::set<u64, cmp> q(cmpElems{tanks, fuel});

	q.clear();
	tanks[src] = 0;
	fuel[src] = l;
	/*for(u64 i=1; i<=n; i++)
	{
		q.insert(i);
	}*/

	q.insert(src);

	while(!q.empty())
	{
		V& u = g.vtx(*(q.begin()));
		q.erase(u.id);

		//std::clog << "popped: " << u.id << "\n";
		for(u64 i=0; i<u.adj.size(); i++)
		{
			V& v = g.vtx(u.adj[i].first);
			//std::clog << "u->v: " << u.id << " -> " << v.id << "\n";
			if(u.id == v.id) continue;
			u64 cost = u.adj[i].second;
			if(cost > l) continue;

			i64 tmp_fuel = fuel[u.id] - cost;
			u64 tmp_tanks = tanks[u.id];
			if(tmp_fuel < 0)
			{
				tmp_tanks++;
				tmp_fuel = l-cost;
			}

			//std::clog << "FUEL:\tSRC = " << fuel[u.id] << " DST = " << tmp_fuel  
			//		  << "\nTANKS:\tSRC = " << tanks[v.id]  << " DST = " << tmp_tanks << "\n";

			if(tmp_tanks < tanks[v.id] || (tmp_tanks == tanks[v.id] && tmp_fuel > fuel[v.id]))
			{
				//std::clog << "updating: " << v.id << "\n";
				q.erase(v.id);
				//std::clog << "after erase\n";
				tanks[v.id] = tmp_tanks;
				fuel[v.id] = tmp_fuel;

				q.insert(v.id);
			}
		}

	}

	return tanks;
}

int main()
{
	std::ios_base::sync_with_stdio(0);
	
	u64 n;
	u64 m;
	u64 l;

	std::cin >> n >> m >> l;

	G g{n};

	for(u64 i=0; i<m; i++)
	{
		u64 a;
		u64 b;
		u64 w;
		std::cin >> a >> b >> w;
		g.EdgeUW(a, b, w);
	}

	u64 q;
	std::cin >> q;

	std::vector<std::pair<u64, u64>> qs;
	qs.reserve(q);

	std::set<u64> qa;

	for(u64 i=0; i<q; i++)
	{
		u64 a;
		u64 b;
		std::cin >> a >> b;
		qs.emplace_back(a,b);
		qa.insert(a);
	}

	std::unordered_map<u64, std::vector<u64>> res;

	for(auto it = qa.begin(); it != qa.end(); it++)
	{
		res[*it] = Dijkstra(n, g, *it, l);
	}

	for(u64 i=0; i<q; i++)
	{
		u64 a;
		u64 b;
		a = qs[i].first;
		b = qs[i].second;
		
		if(res[a][b] == INF)
		{
			std::cout << "-1\n";
		}
		else
		{
			std::cout << res[a][b] << "\n";
		}
	}

	return 0;
}

Measured memory_bytes: 3968