#include<bits/stdc++.h>
#include<string.h>
 
typedef long long int ll;
#define all(x) (x).begin(), (x).end()
 
using namespace std;

int nxt() {
    int x;
    cin >> x;
    return x;
}

ll nxtl(){
    ll x;
    cin>>x;
    return x;
}
 
void SieveOfEratosthenes(int n,vector <int> &primes) 
{ 
    // Create a boolean array "prime[0..n]" and initialize 
    // all entries it as true. A value in prime[i] will 
    // finally be false if i is Not a prime, else true. 
    bool prime[n+1]; 
    memset(prime, true, sizeof(prime)); 
  
    for (int p=2; p*p<=n; p++) 
    { 
        // If prime[p] is not changed, then it is a prime 
        if (prime[p] == true) 
        { 
            // Update all multiples of p greater than or  
            // equal to the square of it 
            // numbers which are multiple of p and are 
            // less than p^2 are already been marked.  
            for (int i=p*p; i<=n; i += p) 
                prime[i] = false; 
        } 
    } 
  
    // Print all prime numbers 
    for (int p=2; p<=n; p++) 
       if (prime[p]) 
          primes.push_back(p);
} 
 
ll max(ll a,ll b)
{
    if(a>b)
        return a;
    return b;
}
 
ll power(ll x, ll y,ll mod) 
{ 
    ll temp; 
    if( y == 0) 
        return 1; 
    temp = power(x, y/2,mod); 
    if (y%2 == 0) 
        return (temp*temp)%mod; 
    else
        return (((x*temp)%mod)*temp)%mod; 
} 

vector <vector <pair<int,int> > > g;
int n;int m;ll l;
vector <vector <ll> > v;
void cal();
void dij(int root,vector <bool> &visited);
vector <vector <int > > g2;
vector <vector <int> > v2;
void bfs(int s,vector <bool> visited);
void floydWarshall () ;

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    n=nxt(),m=nxt(),l=nxt();
    vector <pair<int,int> > row;
    g.resize(n+1,row);
    for(int i=0;i<m;i++)
    {
        int u=nxt(),v=nxt(),c=nxt();
        if(c>l)
            continue;
        g[u].push_back({v,c});
        g[v].push_back({u,c});
    }
    vector <ll> row2;
    row2.resize(n+1,1e16);
    v.resize(n+1,row2);
    floydWarshall();

    /*for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            cout<<v[i][j]<<" ";
        cout<<"\n";
    }*/

    vector <int > row3;
    g2.resize(n+1,row3);
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(v[i][j]<=l||v[j][i]<=l)
            {
                g2[i].push_back(j);
                g2[j].push_back(i);
                //cout<<"pushed "<<i<<" "<<j<<"\n";
            }
        }

    vector <int> row4;
    row4.resize(n+1,-1);
    v2.resize(n+1,row4);
    vector <bool> visited2;
    visited2.resize(n+1,0);
    for(int i=1;i<=n;i++)
        if(!visited2[i])
            bfs(i,visited2);

    /*for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            cout<<v2[i][j]<<" ";
        cout<<"\n";
    }*/

    int q=nxt();
    while(q--)
    {
        int s3=nxt(),t3=nxt();
        if(v2[s3][t3]==-1&&v2[t3][s3]==-1)
            cout<<"-1\n";
        else
            cout<<max(v2[s3][t3]-1,v2[t3][s3]-1)<<"\n";
    }


    
    
    return 0;   
}

void cal()
{
    vector <bool> visited;
    visited.resize(n+1,0);
    for(int i=1;i<=n;i++)
    {
            dij(i,visited);
            for(int i=1;i<=n;i++)
                visited[i]=0;
       
    }

}

void dij(int root,vector <bool> &visited)
{//cout<<"called: "<<root<<"\n";
    v[root][root]=0;
    map <ll,set <int> >  m2;
    set <int > s2;
    m2[0]=s2;
    m2[0].insert(root);
    visited[root]=1;
    while(m2.size()>0)
    {
        auto it=m2.begin();
        ll val=it->first;
        int s=*((it->second).begin());
        (it->second).erase(s);
        if((it->second).size()==0)
            m2.erase(it);
        for(int i=0;i<g[s].size();i++)
        {
            auto p=g[s][i];
            ll new_val=val+p.second;
            ll old_val=v[root][p.first];
            if(new_val<old_val){
                bool f=0;

                if(m2.find(old_val)!=m2.end()&&(m2[old_val]).find(p.first)!=(m2[old_val]).end())
                {
                    (m2[old_val]).erase(p.first);
                    if((m2[old_val]).size()==0)
                        m2.erase(old_val);  
                    f=1;
                }


                v[root][p.first]=new_val;
                if(f)
                {
                    if(m2.find(new_val)==m2.end())
                        m2[new_val]=s2;
                    (m2[new_val]).insert(p.first);
                }

            }
            if(!visited[p.first])
            {
                if(m2.find(v[root][p.first])==m2.end())
                    m2[v[root][p.first]]=s2;
                (m2[v[root][p.first]]).insert(p.first);

                visited[p.first]=1;
            }

        }
    }
}


void bfs(int s,vector <bool> visited)
{//cout<<"called: "<<s<<"\n";
    
    visited[s]=1;
    queue <int> q;
    q.push(s);
    v2[s][s]=0;
    while(q.size()>0)
    {
        int x=q.front();
        q.pop();
        for(int i=0;i<g2[x].size();i++)
        {
            if(!visited[g2[x][i]])
            {
                visited[g2[x][i]]=1;
                v2[s][g2[x][i]]=v2[s][x]+1;
                q.push(g2[x][i]);
            }
        }
    }
}

void floydWarshall ()  
{  
    /* dist[][] will be the output matrix  
    that will finally have the shortest  
    distances between every pair of vertices */
    int  i, j, k;  
  
    /* Initialize the solution matrix same  
    as input graph matrix. Or we can say  
    the initial values of shortest distances 
    are based on shortest paths considering  
    no intermediate vertex. */
    for (i = 1; i <= n; i++)  
        for (j=0;j<g[i].size();j++)  
            v[i][g[i][j].first] = g[i][j].second;  
  
    /* Add all vertices one by one to  
    the set of intermediate vertices.  
    ---> Before start of an iteration,  
    we have shortest distances between all  
    pairs of vertices such that the  
    shortest distances consider only the  
    vertices in set {0, 1, 2, .. k-1} as 
    intermediate vertices.  
    ----> After the end of an iteration,  
    vertex no. k is added to the set of  
    intermediate vertices and the set becomes {0, 1, 2, .. k} */
    for (k = 1; k <= n; k++)  
    {  
        // Pick all vertices as source one by one  
        for (i = 1; i <= n; i++)  
        {  
            // Pick all vertices as destination for the  
            // above picked source  
            for (j = 1; j <= n; j++)  
            {  
                // If vertex k is on the shortest path from  
                // i to j, then update the value of dist[i][j]  
                if (v[i][k] + v[k][j] < v[i][j])  
                    v[i][j] = v[i][k] + v[k][j];  
            }  
        }  
    }  

} 


 
 


Measured memory_bytes: 3328