//
//  main.cpp
//

#include <algorithm>
#include <array>
#include <assert.h>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <math.h>
#include <memory>
#include <memory>
#include <queue>
#include <random>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

using ll = int64_t;
using ull = uint64_t;
constexpr ll LL_MAX = numeric_limits<ll>::max();
constexpr ull ULL_MAX = numeric_limits<ull>::max();

template<typename T>
vector<T> make_vec_nd(T init, ll size) {
	return vector<T>(size, init);
}
template<typename T, typename... Args>
auto make_vec_nd(T init, ll size, Args... rest) {
	auto inner = make_vec_nd(init, rest...);
	return vector<decltype(inner)>(size, inner);
}

#define rep(i, a, b) for (ll i = (a); i < (b); i++)
#define rrep(i, a, b) for (ll i = (a)-1; i >= (b); i--)

struct ListCostGraph {
    struct Edge {
        ll from;
        ll to;
        ll cost;
    };
    vector<vector<Edge>> edges;
    
    ListCostGraph(ll size) { edges.resize(size); }
    
    void add_edge(ll from, ll to, ll cost) {
        edges[from].push_back(Edge{from, to, cost});
    }
    
    void add_edge_bidir(size_t a, size_t b, ll cost) {
        add_edge(a, b, cost);
        add_edge(b, a, cost);
    }
    
    vector<ll> dijkstra(ll s) {
        // O(E logV)
        vector<ll> dist(edges.size(), numeric_limits<ll>::max());
        struct P {
            size_t vertex;
            ll distance;
            P(size_t vertex, ll distance)
            : vertex(vertex)
            , distance(distance) {}
        };
        auto compare = [](const P& lhs, const P& rhs) {
            return lhs.distance > rhs.distance;
        };
        priority_queue<P, vector<P>, decltype(compare)> que(compare);
        dist[s] = 0;
        que.push(P(s, 0));
        while (!que.empty()) {
            P p = que.top();
            que.pop();
            size_t v = p.vertex;
            ll d = p.distance;
            if (dist[v] < d) {
                continue;
            }
            for (int i = 0; i < edges[v].size(); i++) {
                const Edge& e = edges[v][i];
                ll new_dist = dist[v] + e.cost;
                if (dist[e.to] <= new_dist) {    // eを使っても最短経路が改善しないとき
                    continue;
                }
                dist[e.to] = new_dist;
                que.push(P(e.to, new_dist));
            }
        }
        return dist;
    }
    
    // returns array of vertices topologically sorted.
    // throw Exception if not dag.
    vector<ll> topological_sort_if_dag() {
        vector<ll> ans;
        vector<uint8_t> visit_flag(edges.size(), 0);
        for (ll i = 0; i < edges.size(); i++) {
            topological_sort_visit(i, visit_flag, ans);
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
    
    void topological_sort_visit(ll v, vector<uint8_t>& visit_flag,
                                vector<ll>& out_sorted) {
        if (visit_flag[v] == 1) {
            throw "Not DAG";
        }
        if (visit_flag[v] == 2) {
            return;
        }
        visit_flag[v] = 1;
        for (Edge e : edges[v]) {
            topological_sort_visit(e.to, visit_flag, out_sorted);
        }
        visit_flag[v] = 2;
        out_sorted.push_back(v);
    }
    
    // 帰りがけ順序を求める
    // out_vertices - 頂点sから到達できる頂点の集合を帰りがけ順序で並べたもの（アペンドされる）
    void post_order(vector<ll>& out_vertices, vector<bool>& visited, ll now) {
        if (visited[now]) {
            return;
        }
        visited[now] = true;
        for (auto& e : edges[now]) {
            post_order(out_vertices, visited, e.to);
        }
        out_vertices.push_back(now);
    }
    
    // 辺を逆にしたグラフを作成
    ListCostGraph reverse_edge() {
        ListCostGraph ret(edges.size());
        for (ll v = 0; v < edges.size(); v++) {
            for (auto& e : edges[v]) {
                ret.add_edge(e.to, e.from, e.cost);
            }
        }
        return ret;
    }
    
    // 強連結成分分解
    // 連結成分間の辺を全て保つので、多重辺ができることに注意
    // idx_map - 元のグラフでの頂点番号から新しいグラフでの頂点番号へのマップ
    ListCostGraph decompose_to_scc(vector<ll>& idx_map) {
        vector<ll> order;
        vector<bool> visited(edges.size());
        for (ll v = 0; v < edges.size(); v++) {
            post_order(order, visited, v);
        }
        ListCostGraph rev = reverse_edge();
        idx_map.resize(edges.size(), -1);
        ll index = 0;
        for (ll v = edges.size() - 1; v >= 0; v--) {
            if (idx_map[order[v]] == -1) {
                rev.dfs_for_sgc(idx_map, index, order[v]);
                index++;
            }
        }
        ListCostGraph ans(index);
        for (ll v = 0; v < edges.size(); v++) {
            for (auto& e : edges[v]) {
                if (idx_map[e.from] != idx_map[e.to]) {
                    ans.add_edge(idx_map[e.from], idx_map[e.to], e.cost);
                }
            }
        }
        return ans;
    }
    
    void dfs_for_sgc(vector<ll>& idx_map, ll index, ll now) {
        if (idx_map[now] >= 0) {
            return;
        }
        idx_map[now] = index;
        for (auto& e : edges[now]) {
            dfs_for_sgc(idx_map, index, e.to);
        }
    }
};

int main() {
    ll N;
    cin >> N;
    ListCostGraph graph(N);
    rep(i,0,N-1) {
        ll a, b, c;
        cin >> a >> b >> c;
        a--;
        b--;
        graph.add_edge_bidir(a, b, c);
    }
    ll Q, K;
    cin >> Q >> K;
    K--;
    vector<ll> dist = graph.dijkstra(K);
    rep(q,0,Q) {
        ll x, y;
        cin >> x >> y;
        x--;
        y--;
        cout << dist[x] + dist[y] << endl;
    }
}


Measured memory_bytes: 12544