#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define reps(i, n) for (int i = 1; i <= (n); ++i)
#define repd(i, n) for (int i = (n - 1); i >= 0; --i)
#define repds(i, n) for (int i = (n); i > 0; --i)
#define loop(i, x, n) for (int i = (x); i < (n); ++i)
#define loops(i, x, n) for (int i = (x); i <= (n); ++i)
#define loopd(i, x, n) for (int i = (x); i > (n); --i)
#define loopds(i, x, n) for (int i = (x); i >= (n); --i)
#define itrep(i, a) for (auto i = begin(a); i != end(a); ++i)
#define itrepd(i, a) for (auto i = rbegin(a); i != rend(a); ++i)
#define all(x) x.begin(), x.end()
using namespace std;
using ll = long long;
using ld = long double;
template <class T>
using priority_queuel = priority_queue<T, vector<T>, greater<T>>;
constexpr ll inf = static_cast<ll>(1e18);
constexpr int iinf = static_cast<int>(1e9);
constexpr double dinf = 1e10;
constexpr ld ldinf = 1e18;
constexpr double eps = 1e-9;
ll mod = static_cast<ll>(1e9 + 7);
template <class T>
constexpr int sz(const T &a) { return (int)a.size(); }
template <class T>
constexpr T pow2(const T a) { return a * a; }
template <class T, class... Args>
constexpr void mins(T &a, Args... args) { a = min<T>({a, args...}); }
template <class T, class... Args>
constexpr void maxs(T &a, Args... args) { a = max<T>({a, args...}); }
template <class A, int N, class T>
void fillArray(A (&array)[N], const T &val) { std::fill((T *)array, (T *)(array + N), val); }

int n, m;
ll l;

struct D {
    int cnt;
    ll tank;
    D() : cnt(iinf), tank(0) {}
    D(int c, ll t) : cnt(c), tank(t) {}
    bool operator<(const D &d) const {
        return cnt < d.cnt || (cnt == d.cnt && tank > d.tank);
    }
    bool operator>(const D &d) const {
        return !(cnt == d.cnt && tank == d.tank) && !(*this < d);
    }
    D &operator+=(ll cost) {
        if (tank >= cost)
            tank -= cost;
        else {
            tank = l - cost;
            ++cnt;
        }
        return *this;
    }
    D operator+(ll cost) const {
        D res(*this);
        return res += cost;
    }
};

vector<pair<int, ll>> g[305];
D d[305][305];
void solve() {
    cin >> n >> m >> l;
    rep(i, m) {
        int u, v;
        ll c;
        cin >> u >> v >> c;
        --u, --v;
        if (c <= l) {
            g[u].emplace_back(v, c);
            g[v].emplace_back(u, c);
        }
    }

    priority_queuel<pair<D, int>> que;
    rep(i, n) {
        d[i][i] = {0, l};
        que.emplace(d[i][i], i);
        while (!que.empty()) {
            auto p = que.top();
            que.pop();
            auto v = p.second;
            if (d[i][v] < p.first) continue;
            rep(j, sz(g[v])) {
                auto nv = g[v][j];
                if (d[i][nv.first] > d[i][v] + nv.second) {
                    d[i][nv.first] = d[i][v] + nv.second;
                    que.emplace(d[i][nv.first], nv.first);
                }
            }
        }
    }

    int q;
    cin >> q;
    vector<int> ans(q);
    rep(i, q) {
        int s, t;
        cin >> s >> t;
        --s, --t;
        if (d[s][t].cnt >= iinf)
            ans[i] = -1;
        else
            ans[i] = d[s][t].cnt;
    }
    for (auto &val : ans)
        cout << val << endl;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    solve();
    return 0;
}


Measured memory_bytes: 5380