#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#define _USE_MATH_DEFINES
#include <cmath>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
using namespace std;

#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()

const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007; // 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};

struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    cerr << fixed << setprecision(10);
  }
} iosetup;
/*-------------------------------------------------*/
template <typename T>
struct WarshallFloyd {
  vector<vector<T> > graph, dist;

  WarshallFloyd(const vector<vector<T> > &graph, T TINF) : graph(graph), TINF(TINF) {
    n = graph.size();
    dist = graph;
    internal.assign(n, vector<int>(n, -1));
    REP(k, n) REP(i, n) REP(j, n) {
      if (dist[i][k] != TINF && dist[k][j] != TINF && dist[i][j] > dist[i][k] + dist[k][j]) {
        dist[i][j] = dist[i][k] + dist[k][j];
        internal[i][j] = k;
      }
    }
  }

  void add(int src, int dst, T cost) {
    srcs.emplace_back(src);
    dsts.emplace_back(dst);
    costs.emplace_back(cost);
  }

  void calc() {
    set<int> ver;
    int sz = srcs.size();
    REP(i, sz) {
      int s = srcs[i], t = dsts[i];
      T cost = costs[i];
      graph[s][t] = min(graph[s][t], cost);
      if (dist[s][t] >= cost) {
        dist[s][t] = cost;
        internal[s][t] = -1;
      }
      ver.insert(s);
      ver.insert(t);
    }
    for (int v : ver) {
      REP(i, n) REP(j, n) {
        if (dist[i][v] != TINF && dist[v][j] != TINF && dist[i][j] > dist[i][v] + dist[v][j]) {
          dist[i][j] = dist[i][v] + dist[v][j];
          internal[i][j] = v;
        }
      }
    }
    srcs.clear();
    dsts.clear();
    costs.clear();
  }

  bool has_negative_cycle() {
    REP(i, n) if (dist[i][i] < 0) return true;
    return false;
  }

  vector<int> build_path(int s, int t) {
    vector<int> res;
    if (dist[s][t] != TINF) {
      build_path(s, t, res);
      res.emplace_back(t);
    }
    return res;
  }

private:
  const T TINF;
  int n;
  vector<vector<int> > internal;
  vector<int> srcs, dsts;
  vector<T> costs;

  void build_path(int s, int t, vector<int> &path) {
    int k = internal[s][t];
    if (k == -1) path.emplace_back(s);
    else {
      build_path(s, k, path);
      build_path(k, t, path);
    }
  }
};

int main() {
  int n, m, l; cin >> n >> m >> l;
  vector<vector<long long> > graph(n, vector<long long>(n, LINF));
  while (m--) {
    int a, b, c; cin >> a >> b >> c; --a; --b;
    graph[a][b] = graph[b][a] = c;
  }
  WarshallFloyd<long long> wf(graph, LINF);
  vector<vector<long long> > graph2(n, vector<long long>(n, LINF));
  REP(i, n) REP(j, n) {
    if (wf.dist[i][j] <= l) graph2[i][j] = 1;
  }
  WarshallFloyd<long long> wf2(graph2, LINF);
  int q; cin >> q;
  while (q--) {
    int s, t; cin >> s >> t; --s; --t;
    cout << (wf2.dist[s][t] == LINF ? -1 : wf2.dist[s][t] - 1) << '\n';
  }
  return 0;
}


Measured memory_bytes: 5632