trait Monoid {
    type T: Clone;
    fn id() -> Self::T;
    fn op(a: &Self::T, b: &Self::T) -> Self::T;
}

struct SegmentTree<M: Monoid> {
    dat: Vec<M::T>,
    size: usize,
}

#[allow(dead_code)]
impl<M: Monoid> SegmentTree<M> {
    pub fn new(n: usize) -> Self {
        let mut sz = 1;
        while sz < n {
            sz *= 2;
        }
        let mut res = SegmentTree {
            dat: vec![M::id(); sz * 2],
            size: sz,
        };
        res.initialize();
        res
    }

    pub fn update(&mut self, i: usize, x: M::T) {
        assert!(i <= self.size);

        let mut i = i + self.size;
        self.dat[i] = x;
        while i >= 1 {
            self.dat[i / 2] = M::op(&self.dat[i], &self.dat[i ^ 1]);
            i /= 2;
        }
    }

    pub fn accumulate(&self, l: usize, r: usize) -> M::T {
        assert!(l <= r);
        assert!(r <= self.size);

        let (mut l, mut r) = (l + self.size, r + self.size);
        let (mut al, mut ar) = (M::id(), M::id());
        while l < r {
            if l & 1 == 1 {
                al = M::op(&al, &self.dat[l]);
                l += 1;
            }
            if r & 1 == 1 {
                r -= 1;
                ar = M::op(&self.dat[r], &ar);
            }
            l /= 2;
            r /= 2;
        }
        M::op(&al, &ar)
    }

    pub fn fill(&mut self, x: &M::T) {
        for e in self.dat.iter_mut() {
            *e = x.clone();
        }
        self.initialize();
    }

    fn initialize(&mut self) {
        for i in (1..self.size).rev() {
            self.dat[i] = M::op(&self.dat[i * 2 + 0], &self.dat[i * 2 + 1]);
        }
    }
}

use std::iter::*;
impl<M: Monoid> FromIterator<M::T> for SegmentTree<M> {
    fn from_iter<I: IntoIterator<Item = M::T>>(iter: I) -> Self {
        let mut preload = iter.into_iter().collect::<Vec<M::T>>();
        let n = preload.len();
        let mut sz = 1;
        while sz < n { sz *= 2 }
        let mut dat = vec![M::id(); sz];
        dat.reserve(sz);
        for x in preload.drain(..) { dat.push(x) }
        while dat.len() < sz * 2 { dat.push(M::id()) }
        let mut res = SegmentTree { dat: dat, size: sz };
        res.initialize();
        res
    }
}

type Weight = u64;

struct MinPairMonoid;
impl Monoid for MinPairMonoid {
    type T = (Weight, usize);
    fn id() -> Self::T {
        (Weight::max_value(), usize::max_value())
    }
    fn op(a: &Self::T, b: &Self::T) -> Self::T {
        std::cmp::min(*a, *b)
    }
}

type Rmq = SegmentTree<MinPairMonoid>;

struct Lca {
    n: usize,
    graph: Vec<Vec<(usize, Weight)>>,
    tour: Vec<(Weight, usize)>,
    pos: Vec<usize>,
    depth: Vec<Weight>,
    rmq: Rmq,
}


#[allow(dead_code)]
impl Lca {
    pub fn new(n: usize) -> Self {
        Lca {
            n: n,
            graph: vec![vec![]; n],
            tour: vec![],
            pos: vec![],
            depth: vec![],
            rmq: Rmq::new(0),
        }
    }

    pub fn add_edge(&mut self, a: usize, b: usize) {
        self.graph[a].push((b, 1));
        self.graph[b].push((a, 1));
    }

    pub fn add_edge_with_weight(&mut self, a: usize, b: usize, w: Weight) {
        self.graph[a].push((b, w));
        self.graph[b].push((a, w));
    }

    pub fn exec(&mut self, root: usize) {
        self.pos = vec![self.n; self.n];
        self.depth = vec![Weight::max_value(); self.n];
        let mut k = 0;
        let mut g = Vec::new();
        std::mem::swap(&mut g, &mut self.graph);
        self.dfs(root, g.len(), 0, &mut k, &mut g);
        std::mem::swap(&mut g, &mut self.graph);
        self.rmq = Rmq::from_iter(self.tour.clone());
    }

    pub fn lca(&mut self, a: usize, b: usize) -> usize {
        let (ia, ib) = (self.pos[a], self.pos[b]);
        let (_, l) = if ia <= ib {
            self.rmq.accumulate(ia, ib + 1)
        } else {
            self.rmq.accumulate(ib, ia + 1)
        };
        l
    }

    fn dfs(&mut self, v: usize, p: usize, d: Weight, k: &mut usize, g: &Vec<Vec<(usize, Weight)>>) {
        self.tour.push((d, v));
        if self.pos[v] == self.n {
            self.pos[v] = *k;
            self.depth[v] = d;
        }
        *k += 1;
        for &(c, w) in &g[v] {
            if c != p {
                self.dfs(c, v, d + w, k, g);
                self.tour.push((d, v));
                *k += 1;
            }
        }
    }
}

use std::io::*;
use std::fmt::Write;

fn rusize(s: &mut StdinLock) -> Option<usize> {
    let iter = s.by_ref()
        .bytes()
        .map(|c| c.unwrap() as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace());
    let (res, len) = iter.fold((0, 0), |(r, l), x| {
        ((x as u8 - b'0') as usize + r * 10, l + 1)
    });
    if len != 0 { Some(res) } else { None }
}

fn ru64(s: &mut StdinLock) -> Option<u64> {
    let iter = s.by_ref()
        .bytes()
        .map(|c| c.unwrap() as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace());
    let (res, len) = iter.fold((0, 0), |(r, l), x| {
        ((x as u8 - b'0') as u64 + r * 10, l + 1)
    });
    if len != 0 { Some(res) } else { None }
}

fn main() {
    let s = stdin();
    let mut s = s.lock();
    let mut buf = String::new();
    while let Some(n) = rusize(&mut s) {
        let mut lca = Lca::new(n);
        for _ in 0..n - 1 {
            let a = rusize(&mut s).unwrap() - 1;
            let b = rusize(&mut s).unwrap() - 1;
            let c = ru64(&mut s).unwrap();
            lca.add_edge_with_weight(a, b, c);
        }

        let q = rusize(&mut s).unwrap();
        let k = rusize(&mut s).unwrap() - 1;
        lca.exec(k);

        for _ in 0..q {
            let (a, b) = (rusize(&mut s).unwrap() - 1, rusize(&mut s).unwrap() - 1);
            let ans = lca.depth[a] + lca.depth[b];
            writeln!(&mut buf, "{}", ans).unwrap();
        }
    }
    print!("{}", buf);
}


Measured memory_bytes: 41332