use std::io::Write;

#[allow(unused)]
macro_rules! debug {
    ($($format:tt)*) => (write!(std::io::stderr(), $($format)*).unwrap());
}
#[allow(unused)]
macro_rules! debugln {
    ($($format:tt)*) => (writeln!(std::io::stderr(), $($format)*).unwrap());
}

const INF: usize = std::usize::MAX >> 2;

fn main() {
    let (n, m, l) = {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).unwrap();
        let s = s.trim_right().to_owned();
        let mut ws = s.split_whitespace();
        let a: usize = ws.next().unwrap().parse().unwrap();
        let b: usize = ws.next().unwrap().parse().unwrap();
        let c: usize = ws.next().unwrap().parse().unwrap();
        (a, b, c)
    };

    let mut a: Vec<usize> = Vec::new();
    let mut b: Vec<usize> = Vec::new();
    let mut c: Vec<usize> = Vec::new();
    for _ in 0..m {
        let (ai, bi, ci) = {
            let mut s = String::new();
            std::io::stdin().read_line(&mut s).unwrap();
            let s = s.trim_right().to_owned();
            let mut ws = s.split_whitespace();
            let a: usize = ws.next().unwrap().parse().unwrap();
            let b: usize = ws.next().unwrap().parse().unwrap();
            let c: usize = ws.next().unwrap().parse().unwrap();
            (a, b, c)
        };
        a.push(ai);
        b.push(bi);
        c.push(ci);
    }

    let q: usize =  {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).unwrap();
        let s = s.trim_right().to_owned();
        s.parse().unwrap()
    };

    let mut s: Vec<usize> = Vec::new();
    let mut t: Vec<usize> = Vec::new();
    for _ in 0..q {
        let (si, ti) = {
            let mut s = String::new();
            std::io::stdin().read_line(&mut s).unwrap();
            let s = s.trim_right().to_owned();
            let mut ws = s.split_whitespace();
            let a: usize = ws.next().unwrap().parse().unwrap();
            let b: usize = ws.next().unwrap().parse().unwrap();
            (a, b)
        };
        s.push(si);
        t.push(ti);
    }

    solve(n, m, l, a, b, c, q, s, t);
}

fn solve(n: usize, m: usize, l: usize, a: Vec<usize>, b: Vec<usize>, c: Vec<usize>, q: usize, s: Vec<usize>, t: Vec<usize>) {
    let mut graph_mat = vec![vec![false; n + 1]; n + 1];
    let mut lengths = vec![vec![0; n + 1]; n + 1];
    for i in 0..m {
        graph_mat[a[i]][b[i]] = true;
        lengths[a[i]][b[i]] = c[i];
        // 無向グラフに注意
        graph_mat[b[i]][a[i]] = true;
        lengths[b[i]][a[i]] = c[i];
    }

    let distances = warshall_floyd(&graph_mat, &lengths);
    // debugln!("{:#?}", distances);

    let mut graph2 = vec![vec![false; n + 1]; n + 1];
    for i in 1..(n + 1) {
        for j in 1..(n + 1) {
            if distances[i][j] <= l {
                graph2[i][j] = true;
            }
        }
    }
    // debugln!("{:#?}", graph2);
    let lengths2 = vec![vec![1; n + 1]; n + 1];

    let supplies = warshall_floyd(&graph2, &lengths2);
    // debugln!("{:#?}", supplies);

    for i in 0..q {
        let ans = if supplies[s[i]][t[i]] < INF {
            supplies[s[i]][t[i]] as isize - 1
        } else {
            -1
        };

        println!("{}", ans);
    }
}

fn warshall_floyd(graph_mat: &Vec<Vec<bool>>, lengths: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
    let n = graph_mat.len() - 1;

    let mut d = vec![vec![INF; n + 1]; n + 1];
    for i in 1..(n + 1) {
        for j in 1..(n + 1) {
            if graph_mat[i][j] {
                d[i][j] = lengths[i][j];
            }
        }
    }
    for i in 1..(n + 1) {
        d[i][i] = 0;
    }

    for k in 1..(n + 1) {
        for i in 1..(n + 1) {
            for j in 1..(n + 1) {
                if d[i][j] > d[i][k] + d[k][j] {
                    d[i][j] = d[i][k] + d[k][j];
                }
            }
        }
    }

    d
}


Measured memory_bytes: 10620