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

#define debug(x) cout <<"DEBUG"<<" "<<#x<<":"<<x<<'\n'

//↓0-originか1-originでn回繰り返し
#define rep(i,n) for(int i = 0; i < ((int)(n)); i++)   //0-origin昇順
#define rep1(i,n) for(int i = 1; i <= ((int)(n)); i++) //1-origin昇順
#define rrep(i,n) for(int i = ((int)(n)-1); i >= 0; i--)  //0-origin降順
#define rrep1(i,n) for(int i = ((int)(n)); i >= 1; i--)   //1-origin降順
//rep2 -> 第二引数 m から n 回繰り返し ex) m=5 n=3 なら i=5,i=6,i=7 まで
#define rep2(i,m,n) for(int i = ((int)(m)); i < ((int)(n))+((int)(m)); i++)
#define SIZE(x) ((int)((x).size()))
#define all(x) (x).begin(),(x).end()
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<vi> vii; //2次元配列
typedef vector<ll> vll;
typedef vector<string> vs;
template<class T,class U> inline bool chmax(T &a, const U &b){if(a<b){a=b;return 1;}return 0;}
template<class T,class U> inline bool chmin(T &a, const U &b){if(a>b){a=b;return 1;}return 0;}

const ll inf = numeric_limits<ll>::max();
/*GRAPH_TEMPLATE=============================================*/
template<typename T>
class Edge {
public:
    int srch; //searched?探索状態記録「null = -1」
    int to; //辺の行き先
    T cost; //辺の重み
    Edge(int t, T w) : srch(-1), to(t), cost(w) {}
    Edge(int src, int t, T w) : srch(src), to(t), cost(w) {}
};
template<typename T>
using W_Graph = vector<vector<Edge<T>>>;   //重み付きグラフ
using Graph = vector<vector<int>>;         //通常グラフ
template<typename T>
using Matrix = vector<vector<T>>;          //隣接行列
/*FUNCs=================================================*/

/*MAIN==================================================*/
int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);   //cin cout 高速化

    //MAKING GRAPH
    int n, m, l; cin >> n >> m >> l;
    W_Graph<ll> G(n);
    rep(i, m) {
        int a,b; ll c; cin >> a >> b >> c; a--;b--;
        if(c > l) continue;  //このケースのルートは通れないので枝刈り
        G[a].emplace_back(b, c);
        G[b].emplace_back(a, c);
    }
    //MAKING Table with dijkstra
    using P = pair<ll, ll>;  //★優先度的にcnt,distの順! <charging_cnt, dist>
    vector<vector<P>> rec(n, vector<P>(n, make_pair(inf,inf)));  //recording 

    using TP = pair<P, int>;    // <cnt, dist, id> //優先度的にcnt,distの順!
    priority_queue<TP, vector<TP>, greater<TP>> que;

    for(int i = 0; i < n; ++i) {
        rec[i][i] = make_pair(0LL, 0LL);
        que.emplace(rec[i][i], i);

        while(que.size()) {
            auto p = que.top(); que.pop();
            ll cnt = p.first.first;
            ll dist = p.first.second;
            int id = p.second;
            if(dist > rec[i][id].second) continue;  //やっぱいるね。うん

            for(auto &edge : G[id]) {
                ll new_dist = dist + edge.cost;
                ll new_cnt = cnt;
                //補給の処理
                if(new_dist > l) {
                    new_dist = edge.cost;
                    new_cnt++;
                }

                P next_p = make_pair(new_cnt, new_dist);
                if(chmin(rec[i][edge.to], next_p)) {
                    que.emplace(rec[i][edge.to], edge.to);
                }
            }
        }
    }

    //ANSWER to Query
    int q; cin >> q;
    rep(i, q) {
        int s, t; cin >> s >> t; --s; --t;
        if(rec[s][t].first == inf) cout << -1 << '\n';
        else cout << rec[s][t].first << '\n';
    }
}

Measured memory_bytes: 7040