Language: C++

use std::collections::{BinaryHeap, HashMap};
use std::io::{self, BufRead, BufWriter, Write};

fn solve<R, W>(reader: R, mut writer: W)
where
    R: BufRead,
    W: Write,
{
    let mut lines = reader.lines();
    let a_line = lines.next().unwrap().unwrap();
    let mut splited = a_line.trim().split_whitespace();
    let n: usize = splited.next().unwrap().parse().unwrap();
    let m: usize = splited.next().unwrap().parse().unwrap();
    let l: i32 = splited.next().unwrap().parse().unwrap();

    let mut distance: HashMap<usize, HashMap<usize, i32>> = HashMap::new();
    for _ in 1..m + 1 {
        let a_line = lines.next().unwrap().unwrap();
        let mut splited = a_line.trim().split_whitespace();
        let a: usize = splited.next().unwrap().parse().unwrap();
        let b: usize = splited.next().unwrap().parse().unwrap();
        let c: i32 = splited.next().unwrap().parse().unwrap();
        if c > l {
            continue;
        }

        {
            let entry = distance.entry(a).or_insert(HashMap::new());
            entry.insert(b, c);
        }
        {
            let entry = distance.entry(b).or_insert(HashMap::new());
            entry.insert(a, c);
        }
    }

    // make tables for all nodes. use from 1 to n (don't use 0)
    let mut results: Vec<Vec<(i32, i32, usize)>> = vec![vec![(0, 0, 0)]; n + 1];
    for source in 1..n + 1 {
        results[source] = dijkstra(&distance, n, l, source);
    }

    let _ = lines.next();
    let query = lines.map(|s| {
        let unwraped = s.unwrap();
        let mut splited = unwraped.trim().split_whitespace();
        let s: usize = splited.next().unwrap().parse().unwrap();
        let t: usize = splited.next().unwrap().parse().unwrap();
        (s, t)
    });
    for (s, t) in query {
        let table = &results[s];
        let (_, count, _) = table[t];
        writeln!(&mut writer, "{}", if count >= MAX { -1 } else { count }).unwrap();
    }
}

#[derive(Debug, PartialEq, Eq)]
struct QueueItem {
    gas_left: i32,
    count: i32,
    node: usize,
}

impl QueueItem {
    fn new(gas_left: i32, count: i32, node: usize) -> Self {
        QueueItem {
            gas_left: gas_left,
            count: count,
            node: node,
        }
    }
}

use std::cmp::Ordering;
impl PartialOrd for QueueItem {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        // lower count is better
        match other.count.cmp(&self.count) {
            Ordering::Equal => Some(self.gas_left.cmp(&other.gas_left)),
            x => Some(x),
        }
    }
}

impl Ord for QueueItem {
    fn cmp(&self, other: &Self) -> Ordering {
        match other.count.cmp(&self.count) {
            Ordering::Equal => self.gas_left.cmp(&other.gas_left),
            x => x,
        }
    }
}

static MAX: i32 = 1000;
fn dijkstra(
    distance: &HashMap<usize, HashMap<usize, i32>>,
    n: usize,
    l: i32,
    source: usize,
) -> Vec<(i32, i32, usize)> {
    let mut queue: BinaryHeap<QueueItem> = BinaryHeap::with_capacity(n);
    // use from 1 to n (Don't use 0). gas_left, count, previous_node
    let mut table: Vec<(i32, i32, usize)> = vec![(0, MAX, 0); n + 1];
    queue.push(QueueItem::new(l, 0, source));
    table[source] = (l, 0, 0); // previous_node = 0 means NULL

    while !queue.is_empty() {
        let item = queue.pop().unwrap();
        let neighbors = match distance.get(&item.node) {
            Some(n) => n,
            None => continue,
        };

        for &neighbor in neighbors.keys() {
            if let Some(&d) = neighbors.get(&neighbor) {
                let (new_gas_left, new_count) = if item.gas_left >= d {
                    (item.gas_left - d, item.count)
                } else if l >= d {
                    (l - d, item.count + 1)
                } else {
                    unreachable!();
                };
                let (gas_left, count, _) = table[neighbor];
                if new_count < count || new_count == count && new_gas_left > gas_left {
                    table[neighbor] = (new_gas_left, new_count, item.node);
                    queue.push(QueueItem::new(new_gas_left, new_count, neighbor));
                }
            }
        }
    }

    table
}

fn main() {
    let stdio = io::stdin();
    let input = stdio.lock();

    let stdout = io::stdout();
    let output = BufWriter::new(stdout.lock());

    solve(input, output);
}

#[cfg(test)]
mod tests {
    use super::*;

    const TESTS: &'static [(&'static [u8], &'static [u8])] = &[
        (
            br"3 2 5
1 2 3
2 3 3
2
3 2
1 3",
            br"0
1
",
        ),
        (
            br"4 0 1
1
2 1",
            br"-1
",
        ),
        (
            br"5 4 4
1 2 2
2 3 2
3 4 3
4 5 2
20
2 1
3 1
4 1
5 1
1 2
3 2
4 2
5 2
1 3
2 3
4 3
5 3
1 4
2 4
3 4
5 4
1 5
2 5
3 5
4 5",
            br"0
0
1
2
0
0
1
2
0
0
0
1
1
1
0
0
2
2
1
0
",
        ),
    ];

    #[test]
    fn test_e() {
        for &(input, expected) in TESTS {
            let mut output = Vec::new();
            solve(input, &mut output);
            let expected_str = String::from_utf8(expected.to_vec()).unwrap();
            let output_str = String::from_utf8(output).unwrap();
            assert_eq!(expected_str, output_str);
        }
    }
}


Compiler output:
a.cc:17:14: error: too many decimal points in number
   17 |     for _ in 1..m + 1 {
      |              ^~~~
a.cc:39:19: error: too many decimal points in number
   39 |     for source in 1..n + 1 {
      |                   ^~~~
a.cc:58:2: error: invalid preprocessing directive #[
   58 | #[derive(Debug, PartialEq, Eq)]
      |  ^
a.cc:146:2: error: invalid preprocessing directive #[
  146 | #[cfg(test)]
      |  ^
a.cc:150:19: warning: multi-character literal with 10 characters exceeds 'int' size of 4 bytes
  150 |     const TESTS: &'static [(&'static [u8], &'static [u8])] = &[
      |                   ^~~~~~~~~~~~~~~~~~
a.cc:150:45: warning: missing terminating ' character
  150 |     const TESTS: &'static [(&'static [u8], &'static [u8])] = &[
      |                                             ^
a.cc:150:45: error: missing terminating ' character
  150 |     const TESTS: &'static [(&'static [u8], &'static [u8])] = &[
      |                                             ^~~~~~~~~~~~~~~~~~~
a.cc:152:15: warning: missing terminating " character
  152 |             br"3 2 5
      |               ^
a.cc:152:15: error: missing terminating " character
  152 |             br"3 2 5
      |               ^~~~~~
a.cc:157:4: warning: missing terminating " character
  157 | 1 3",
      |    ^
a.cc:157:4: error: missing terminating " character
  157 | 1 3",
      |    ^~
a.cc:158:15: warning: missing terminating " character
  158 |             br"0
      |               ^
a.cc:158:15: error: missing terminating " character
  158 |             br"0
      |               ^~
a.cc:160:1: warning: missing terminating " character
  160 | ",
      | ^
a.cc:160:1: error: missing terminating " character
  160 | ",
      | ^~
a.cc:163:15: warning: missing terminating " character
  163 |             br"4 0 1
      |               ^
a.cc:163:15: error: missing terminating " character
  163 |             br"4 0 1
      |               ^~~~~~
a.cc:165:4: warning: missing terminating " character
  165 | 2 1",
      |    ^
a.cc:165:4: error: missing terminating " character
  165 | 2 1",
      |    ^~
a.cc:166:15: warning: missing terminating " character
  166 |             br"-1
      |               ^
a.cc:166:15: error: missing terminating " character
  166 |             br"-1
      |               ^~~
a.cc:167:1: warning: missing terminating " character
  167 | ",
      | ^
a.cc:167:1: error: missing terminating " character
  167 | ",
      | ^~
a.cc:170:15: warning: missing terminating " character
  170 |             br"5 4 4
      |               ^
a.cc:170:15: error: missing terminating " character
  170 |             br"5 4 4
      |               ^~~~~~
a.cc:195:4: warning: missing terminating " character
  195 | 4 5",
      |    ^
a.cc:195:4: error: missing terminating " character
  195 | 4 5",
      |    ^~
a.cc:196:15: warning: missing terminating " character
  196 |             br"0
      |               ^
a.cc:196:15: error: missing terminating " character
  196 |             br"0
      |               ^~
a.cc:216:1: warning: missing terminating " character
  216 | ",
      | ^
a.cc:216:1: error: missing terminating " character
  216 | ",
      | ^~
a.cc:220:6: error: invalid preprocessing directive #[
  220 |     #[test]
      |      ^
a.cc:1:1: error: 'use' does not name a type
    1 | use std::collections::{BinaryHeap, HashMap};
      | ^~~
a.cc:2:1: error: 'use' does not name a type
    2 | use std::io::{self, BufRead, BufWriter, Write};
      | ^~~
a.cc:4:1: error: 'fn' does not name a type
    4 | fn solve<R, W>(reader: R, mut writer: W)
      | ^~
a.cc:60:5: error: 'gas_left' does not name a type
   60 |     gas_left: i32,
      |     ^~~~~~~~
a.cc:65:6: error: expected initializer before 'QueueItem'
   65 | impl QueueItem {
      |      ^~~~~~~~~
a.cc:75:1: error: 'use' does not name a type
   75 | use std::cmp::Ordering;
      | ^~~
a.cc:76:1: error: 'impl' does not name a type
   76 | impl PartialOrd for QueueItem {
      | ^~~~
a.cc:86:1: error: 'impl' does not name a type
   86 | impl Ord for QueueItem {
      | ^~~~
a.cc:95:11: error: found ':' in nested-name-specifier, expected '::'
   95 | static MAX: i32 = 1000;
      |           ^
      |           ::
a.cc:95:8: error: 'MAX' does not name a type
   95 | static MAX: i32 = 1000;
      |        ^~~
a.cc:96:1: error: 'fn' does not name a type
   96 | fn dijkstra(
      | ^~
a.cc:136:1: error: 'fn' does not name a type
  136 | fn main() {
      | ^~
a.cc:147:1: error: 'mod' does not name a type
  147 | mod tests {
      | ^~~