#include <bits/stdc++.h>
#include <stdio.h>

using namespace std;
#define inputInt(a) int a; cin >> a; 
#define inputInt2(a,b) int a; int b; cin >> a >> b; 
#define inputInt3(a,b,c) int a; int b; int c; cin >> a >> b >> c;
#define inputLong(a) long a;cin >> a; 
#define inputIntArray(a,N) int a[N];for(int i=0;i<N;i++){cin >> a[i];}
#define inputLongArray(a,N) long a[N];for(int i=0;i<N;i++){cin >> a[i];}
#define inputIntArray2(a,b,N) int a[N]; int b[N]; for(int i=0;i<N;i++){cin >> a[i] >> b[i];}
#define output(answer) cout << answer << endl;
#define fN(i,N)    for(int i=0; i<N; i++)
#define fSE(i,s,e) for(int i=s; i<=e; i++)
#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int iINF = 1e9;
const ll INF = 1e18;
int L;

class Graph{
  vector<vector<pair<int,ll>>> graph;//graph[from][i番目の辺].<to,cost>
  vector<vector<ll>> d;
  
  public:
  int node_num;
  
  Graph(int N, int M, bool isDirected = false):graph(N,vector<pair<int,ll>>(N,{iINF,INF})),node_num(N){//コンストラクタ
    //多重辺が存在しないと仮定して良い？→高々N
    for(int i=0; i<M; ++i){
      int from, to, cost; cin >> from >> to >> cost;
      from --; to --;
      graph[from].pb(mp(to,cost));
      if(!isDirected){graph[to].pb(mp(from,cost));}//無向グラフの時
      //cout << from << " " << to << " " << cost << " " << endl; 
    }
  }
  
  Graph(vector<vector<ll>> d, bool isDirected = 0):
  graph(d.size(),vector<pair<int,ll>>(d.size(),{iINF,INF})),node_num(d.size()){//WarshallFloydの結果からGraphを初期化する。
    for(int i=0; i<node_num; ++i){
      for(int j=0; j<node_num; ++j){
        if(d[i][j] <= L){
          graph[i].pb(mp(j,1));
          graph[j].pb(mp(i,1));
        }
      }
    } 
  }
  
  vector<vector<ll>> WarshallFloyd(){
    int N = node_num;
    vector<vector<ll>> distance(N,vector<ll>(N,INF));
  
    for(int i=0; i<N; i++){//自己ループ
      distance[i][i] = 0;
    }
    for(int i=0; i<N; i++){//初期化
      for(auto edge:graph[i]){
         if(edge.first == iINF){continue;}
         distance[i][edge.first] = min(distance[i][edge.first],edge.second);//多重辺対策
         //cout << i << " " << edge.first << " " << edge.second << endl;
      }
    }
    for(int k=0; k<N; k++){//経由する頂点
      for(int i=0; i<N; i++){//始点
        for(int j=0; j<N; j++){//終点
          distance[i][j] = min(distance[i][j], distance[i][k]+distance[k][j]);
          //if(distance[i][j] == distance[i][k]+distance[k][j])
          //{ cout << i<< " "<<j<<" " <<" changed" <<endl;}
        }
      }
    }
    return distance;
  }
  
  inline vector<pair<int,ll>> operator [] (int index) const{//読み取り
     return graph[index];
  }
  inline vector<pair<int,ll>>& operator [] (int index){//書き取り
     return graph[index];
  }
};

int main()
{
  
  //input
  int N, M; cin >> N >> M >> L;
  //cout << N << M << L << endl;
  
  Graph graph(N,M,0);
  //cout << graph.node_num << endl;
  auto d = graph.WarshallFloyd();
  
  
  Graph graph2(d,0);
  auto d2 = graph2.WarshallFloyd();
  
  // output
  
  int Q; cin >> Q;
  for(int i=0; i<Q; i++){
    int s, t; cin >> s >> t; s--; t--;
    if(d2[s][t] != INF){cout << d2[s][t]-1 << endl;}
    else{cout << -1 << endl;}
  }
  
  return 0;
}

Measured memory_bytes: 10240