Problem:
Score : 400 points

Problem Statement

You are given a tree with N vertices.

Here, a tree is a kind of graph, and more specifically, a connected undirected graph with N-1 edges, where N is the number of its vertices.

The i-th edge (1≤i≤N-1) connects Vertices a_i and b_i, and has a length of c_i.

You are also given Q queries and an integer K. In the j-th query (1≤j≤Q):

find the length of the shortest path from Vertex x_j and Vertex y_j via Vertex K.

Constraints

3≤N≤10^5

1≤a_i,b_i≤N (1≤i≤N-1)

1≤c_i≤10^9 (1≤i≤N-1)

The given graph is a tree.

1≤Q≤10^5

1≤K≤N

1≤x_j,y_j≤N (1≤j≤Q)

x_j≠y_j (1≤j≤Q)

x_j≠K,y_j≠K (1≤j≤Q)

Input

Input is given from Standard Input in the following format:

N
a_1 b_1 c_1
:
a_{N-1} b_{N-1} c_{N-1}
Q K
x_1 y_1
:
x_{Q} y_{Q}

Output

Print the responses to the queries in Q lines.

In the j-th line j(1≤j≤Q), print the response to the j-th query.

Sample Input 1

5
1 2 1
1 3 1
2 4 1
3 5 1
3 1
2 4
2 3
4 5

Sample Output 1

3
2
4

The shortest paths for the three queries are as follows:

Query 1: Vertex 2 → Vertex 1 → Vertex 2 → Vertex 4 : Length 1+1+1=3

Query 2: Vertex 2 → Vertex 1 → Vertex 3 : Length 1+1=2

Query 3: Vertex 4 → Vertex 2 → Vertex 1 → Vertex 3 → Vertex 5 : Length 1+1+1+1=4

Sample Input 2

7
1 2 1
1 3 3
1 4 5
1 5 7
1 6 9
1 7 11
3 2
1 3
4 5
6 7

Sample Output 2

5
14
22

The path for each query must pass Vertex K=2.

Sample Input 3

10
1 2 1000000000
2 3 1000000000
3 4 1000000000
4 5 1000000000
5 6 1000000000
6 7 1000000000
7 8 1000000000
8 9 1000000000
9 10 1000000000
1 1
9 10

Sample Output 3

17000000000

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

// ABC 070 D Transit Tree Path

//#define TEST

using System;
using System.Collections.Generic;
using System.Linq;
using MS.Internal; //PriorityQueueを用いる

class Program
{
    static int N;
    static Tree t;
    static int Q;
    static int K;

    static void Main()
    {
        /* 入力を受け取る */
        N = int.Parse(Console.ReadLine());
        t = new Tree(N);
        int[] input;
        for (int i = 0; i < N - 1; i++)
        {
            input = Console.ReadLine().Split().Select(int.Parse).ToArray();
            int a = input[0] - 1;
            int b = input[1] - 1;
            int c = input[2];
            t.SetEdge(a, b, c);
        }
        input = Console.ReadLine().Split().Select(int.Parse).ToArray();
        Q = input[0];
        K = input[1] - 1;

        /* Dijkstra法により、頂点Kから各頂点までの最短距離を求める */
        long[] dis = t.Dijkstra(K);

#if TEST
        foreach (var i in dis) Console.WriteLine(i);
#endif

        /* 各クエリを読み込み、処理 */
        for (int i = 0; i < Q; i++)
        {
            input = Console.ReadLine().Split().Select(int.Parse).ToArray();
            int x = input[0] - 1;
            int y = input[1] - 1;
            Console.WriteLine(dis[x] + dis[y]);
        }
    }
}

struct Node
{
    public int n; //頂点のnumber
    public List<int> next; //隣接する頂点
    public List<int> length; //隣接する頂点までの距離

    public Node(int n) //コンストラクタ
    {
        this.n = n;
        next = new List<int>();
        length = new List<int>();
    }
}

struct Tree
{
    public int n; //頂点数
    public Node[] nodes; //頂点

    public Tree(int n) //コンストラクタ
    {
        this.n = n;
        nodes = new Node[n];
        for (int i = 0; i < n; i++)
            nodes[i] = new Node(i);
    }

    public void SetEdge(int s, int g, int l) //頂点s,g間に長さlの辺を張る
    {
        nodes[s].next.Add(g);
        nodes[s].length.Add(l);
        nodes[g].next.Add(s);
        nodes[g].length.Add(l);
    }

    public long[] Dijkstra(int k) //頂点kから各頂点への最短距離を返す
    {
        /* 初期化 */
        Pair[] p = new Pair[n];
        for (int i = 0; i < n; i++)
            p[i] = new Pair(i, (long)1e15);
        p[k].dis = 0;
        PriorityQueue<Pair> Q = new PriorityQueue<Pair>(0, p[0]);
        foreach (var i in p) Q.Push(i);
        /* 本計算 */
        while (Q.Count > 0)
        {
            var up = Q.Top;
            Q.Pop();
            int u = up.n;
            for (int i = 0; i < nodes[u].next.Count; i++)
            {
                var v = nodes[u].next[i];
                var l = nodes[u].length[i];
                if (p[v].dis > p[u].dis + l)
                {
                    p[v].dis = p[u].dis + l;
                    Q.Push(p[v]);
                }
            }
        }
        long[] dis = new long[n];
        for (int i = 0; i < n; i++)
            dis[i] = p[i].dis;
        return dis;
    }
}

struct Pair : IComparer<Pair>
{
    public int n; //頂点番号
    public long dis; //距離

    public Pair(int n, long dis) //コンストラクタ
    {
        this.n = n;
        this.dis = dis;
    }

    public int Compare(Pair x, Pair y) //Pairの比較
    {
        if (x.dis == y.dis) return 0;
        return x.dis - y.dis > 0 ? 1 : -1;
    }
}

namespace MS.Internal
{
    using System.Diagnostics;
    using System.Collections.Generic;

    /// <summary>
    /// PriorityQueue provides a stack-like interface, except that objects
    /// "pushed" in arbitrary order are "popped" in order of priority, i.e., 
    /// from least to greatest as defined by the specified comparer.
    /// </summary>
    /// <remarks>
    /// Push and Pop are each O(log N). Pushing N objects and them popping
    /// them all is equivalent to performing a heap sort and is O(N log N).
    /// </remarks>
    internal class PriorityQueue<T>
    {
        //
        // The _heap array represents a binary tree with the "shape" property.
        // If we number the nodes of a binary tree from left-to-right and top-
        // to-bottom as shown,
        //
        //             0
        //           /   \
        //          /     \
        //         1       2
        //       /  \     / \
        //      3    4   5   6
        //     /\    /
        //    7  8  9
        //
        // The shape property means that there are no gaps in the sequence of
        // numbered nodes, i.e., for all N > 0, if node N exists then node N-1
        // also exists. For example, the next node added to the above tree would
        // be node 10, the right child of node 4.
        //
        // Because of this constraint, we can easily represent the "tree" as an
        // array, where node number == array index, and parent/child relationships
        // can be calculated instead of maintained explicitly. For example, for
        // any node N > 0, the parent of N is at array index (N - 1) / 2.
        //
        // In addition to the above, the first _count members of the _heap array
        // compose a "heap", meaning each child node is greater than or equal to
        // its parent node; thus, the root node is always the minimum (i.e., the
        // best match for the specified style, weight, and stretch) of the nodes 
        // in the heap.
        //
        // Initially _count < 0, which means we have not yet constructed the heap.
        // On the first call to MoveNext, we construct the heap by "pushing" all
        // the nodes into it. Each successive call "pops" a node off the heap
        // until the heap is empty (_count == 0), at which time we've reached the
        // end of the sequence.
        //

        #region constructors

        internal PriorityQueue(int capacity, IComparer<T> comparer)
        {
            _heap = new T[capacity > 0 ? capacity : DefaultCapacity];
            _count = 0;
            _comparer = comparer;
        }

        #endregion

        #region internal members

        /// <summary>
        /// Gets the number of items in the priority queue.
        /// </summary>
        internal int Count
        {
            get { return _count; }
        }

        /// <summary>
        /// Gets the first or topmost object in the priority queue, which is the
        /// object with the minimum value.
        /// </summary>
        internal T Top
        {
            get
            {
                Debug.Assert(_count > 0);
                return _heap[0];
            }
        }

        /// <summary>
        /// Adds an object to the priority queue.
        /// </summary>
        internal void Push(T value)
        {
            // Increase the size of the array if necessary.
            if (_count == _heap.Length)
            {
                T[] temp = new T[_count * 2];
                for (int i = 0; i < _count; ++i)
                {
                    temp[i] = _heap[i];
                }
                _heap = temp;
            }

            // Loop invariant:
            //
            //  1.  index is a gap where we might insert the new node; initially
            //      it's the end of the array (bottom-right of the logical tree).
            //
            int index = _count;
            while (index > 0)
            {
                int parentIndex = HeapParent(index);
                if (_comparer.Compare(value, _heap[parentIndex]) < 0)
                {
                    // value is a better match than the parent node so exchange
                    // places to preserve the "heap" property.
                    _heap[index] = _heap[parentIndex];
                    index = parentIndex;
                }
                else
                {
                    // we can insert here.
                    break;
                }
            }

            _heap[index] = value;
            _count++;
        }

        /// <summary>
        /// Removes the first node (i.e., the logical root) from the heap.
        /// </summary>
        internal void Pop()
        {
            Debug.Assert(_count != 0);

            if (_count > 1)
            {
                // Loop invariants:
                //
                //  1.  parent is the index of a gap in the logical tree
                //  2.  leftChild is
                //      (a) the index of parent's left child if it has one, or
                //      (b) a value >= _count if parent is a leaf node
                //
                int parent = 0;
                int leftChild = HeapLeftChild(parent);

                while (leftChild < _count)
                {
                    int rightChild = HeapRightFromLeft(leftChild);
                    int bestChild =
                        (rightChild < _count && _comparer.Compare(_heap[rightChild], _heap[leftChild]) < 0) ?
                        rightChild : leftChild;

                    // Promote bestChild to fill the gap left by parent.
                    _heap[parent] = _heap[bestChild];

                    // Restore invariants, i.e., let parent point to the gap.
                    parent = bestChild;
                    leftChild = HeapLeftChild(parent);
                }

                // Fill the last gap by moving the last (i.e., bottom-rightmost) node.
                _heap[parent] = _heap[_count - 1];
            }

            _count--;
        }

        #endregion

        #region private members

        /// <summary>
        /// Calculate the parent node index given a child node's index, taking advantage
        /// of the "shape" property.
        /// </summary>
        private static int HeapParent(int i)
        {
            return (i - 1) / 2;
        }

        /// <summary>
        /// Calculate the left child's index given the parent's index, taking advantage of
        /// the "shape" property. If there is no left child, the return value is >= _count.
        /// </summary>
        private static int HeapLeftChild(int i)
        {
            return (i * 2) + 1;
        }

        /// <summary>
        /// Calculate the right child's index from the left child's index, taking advantage
        /// of the "shape" property (i.e., sibling nodes are always adjacent). If there is
        /// no right child, the return value >= _count.
        /// </summary>
        private static int HeapRightFromLeft(int i)
        {
            return i + 1;
        }

        private T[] _heap;
        private int _count;
        private IComparer<T> _comparer;
        private const int DefaultCapacity = 6;

        #endregion
    }
}