use std::ops::{Index, IndexMut};
use std::cmp::{Ordering};
use std::collections::BinaryHeap;
// use std::clone::Clone;

fn getline() -> String{
    let mut res = String::new();
    std::io::stdin().read_line(&mut res).ok();
    res
}

macro_rules! split {
    ($x: expr) => {
        ($x).trim().split(' ').collect();
    }
}

macro_rules! parse {
    ($x: expr) => {
        ($x).parse().unwrap();
    }
}

fn printvec<T>(v: &Vec<T>) where T: std::fmt::Display {
    for e in v {
        print!("{} ", e);
    }
    println!();
}

type Cost = i64;

struct Edge {
    to: usize,
    cost: Cost,
}

impl std::clone::Clone for Edge {
    fn clone(&self) -> Edge { Edge{to: self.to, cost: self.cost} }
}

impl Ord for Edge {
    fn cmp(&self, other: &Edge) -> Ordering {
        (-self.cost).cmp(&(-other.cost))
    }
}

impl PartialOrd for Edge {
    fn partial_cmp(&self, other: &Edge) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Eq for Edge {}

impl PartialEq for Edge {
    fn eq(&self, other: &Edge) -> bool {
        self.cost == other.cost
    }
}

struct Graph {
    adj: Vec<Vec<Edge>>,
}

impl Index<usize> for Graph {
    type Output = Vec<Edge>;

    fn index(&self, i: usize) -> &Vec<Edge> {
        &self.adj[i]
    }
}

impl IndexMut<usize> for Graph {
    fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut Vec<Edge> {
        &mut self.adj[i]
    }
}

impl Graph {

    fn new(n: usize) -> Graph{
        Graph {
            adj: vec![vec![]; n],
        }
    }

    fn size(&self) -> usize{
        self.adj.capacity()
    }

    fn add_edge(&mut self, from: usize, to_: usize, cost_: Cost) {
        self.adj[from].push(Edge{to: to_, cost: cost_});
    }

    fn add_uedge(&mut self, from: usize, to_: usize, cost_: Cost) {
        self.add_edge(from, to_, cost_);
        self.add_edge(to_, from, cost_);
    }

    fn get_shortest_path(&self, from: usize) -> (Vec<Cost>, Vec<usize>) {
        let n = self.size();
        
        let mut dist = vec![std::i64::MAX; n];
        let mut pre = vec![n as usize; n];
        let mut heap = BinaryHeap::new();
        heap.push(Edge{to: from, cost: 0});
        dist[from] = 0;
        println!();
        while !heap.is_empty() {
            match heap.pop() {
                None => {
                    assert!(true);
                }
                Some(p) => {
                    for e in &(*self)[p.to] {
                        if p.cost+e.cost >= dist[e.to] {
                            continue;
                        }
                        heap.push(Edge{to: e.to, cost: p.cost+e.cost});
                        dist[e.to] = p.cost+e.cost;
                        pre[e.to] = p.to;
                    }
                }
            }
        }
        
        (dist, pre)
    }
}

// fn main() {
//     let s = getline();
//     let iv: Vec<_> = split!(s);
//     let n: usize = parse!(iv[0]);
//     let m: usize = parse!(iv[1]);
//     let mut g = Graph::new(n);
//     for _ in 0..m {
//         let s = getline();
//         let iv: Vec<_> = split!(s);
//         let a: usize = parse!(iv[0]);
//         let b: usize = parse!(iv[1]);
//         let c: Cost = parse!(iv[2]);
//         g.add_uedge(a-1, b-1, c);
//     }

//     let (dist, path) = g.get_shortest_path(0);
//     match dist[n-1] {
//         std::i64::MAX => {
//             println!("{}", -1);
//         }
//         _ => {
//             let mut sta = Vec::new();
//             sta.push(n-1 as usize);
//             let mut p = n-1;
//             while p != 0 {
//                 p = path[p];
//                 sta.push(p);
//             }
//             while let Some(top) = sta.pop() {
//                 print!("{}", top+1);
//                 if sta.len() >= 1 {
//                     print!(" ");
//                 }
//             }
//             println!();
//         }
//     }
// }

fn main() {
    let s = getline();
    
    let iv: Vec<_> = split!(s);
    let n: usize = parse!(iv[0]);
    let mut g = Graph::new(n);
    for _ in 0..(n-1) {
        let s = getline();
        let iv: Vec<_> = split!(s);
        let a: usize = parse!(iv[0]);
        let b: usize = parse!(iv[1]);
        let c: i64 = parse!(iv[2]);
        g.add_uedge(a-1, b-1, c);
    }
    let s = getline();
    let iv: Vec<_> = split!(s);
    let q: usize = parse!(iv[0]);
    let k__: usize = parse!(iv[1]);
    let k = k__-1;
    let mut dist = vec![0 as i64; n];

    fn dfs(g: &Graph, mut dist: Vec<i64>, p: usize, pre: usize) -> Vec<i64> {
        for e in &g[p] {
            if e.to == pre {
                continue;
            }
            dist[e.to] = dist[p]+e.cost;
            dist = dfs(&g, dist, e.to, p);
        }
        dist
    }

    dist = dfs(&g, dist, k, n);

    for _ in 0..q {
        let s = getline();
        let iv: Vec<_> = split!(s);
        let a: usize = parse!(iv[0]);
        let b: usize = parse!(iv[1]);
        println!("{}", dist[a-1]+dist[b-1]);
    }
}

// fn main() {
//     // let mut hoge = BinaryHeap::new();
//     // hoge.push(-1);
//     // hoge.push(1);
//     // hoge.push(100);
//     // hoge.push(5);
//     // while let Some(x) = hoge.pop() {
//     //     println!("{}", x);
//     // }

//     let mut v = vec![-4, 5, 3,3];
//     let hoge:Vec<_> = v.into_iter().map(|c| c*2).collect();
//     printvec(&hoge);
// }


// fn main() {
//     fn f(mut v: Vec<i32>) -> Vec<i32> {
//         v[1] = 100;
//         v
//     }
//     let v = vec![1,2,3];
//     let v = f(v);
//     println!("{}",v[1]);
// }


Measured memory_bytes: 27004