Problem:
Score : 1400 points

Problem Statement

#nck {
width: 30px;
height: auto;
}

In the country there are N cities numbered 1 through N, which are connected by N-1 bidirectional roads. In terms of graph theory, there is a unique simple path connecting every pair of cities. That is, the N cities form a tree. Besides, if we view city 1 as the root of this tree, the tree will be a full binary tree (a tree is a full binary tree if and only if every non-leaf vertex in the tree has exactly two children). Roads are numbered 1 through N-1. The i-th road connects city i+1 and city a_i. When you pass through road i, the toll you should pay is v_i (if v_i is 0, it indicates the road does not require a toll).

A company in city 1 will give each employee a family travel and cover a large part of the tolls incurred. Each employee can design the travel by themselves. That is, which cities he/she wants to visit in each day and which city to stay at each night. However, there are some constraints. More details are as follows:

The travel must start and end at city 1. If there are m leaves in the tree formed by the cities, then the number of days in the travel must be m+1. At the end of each day, except for the last day, the employee must stay at some hotel in a leaf city. During the whole travel, the employee must stay at all leaf cities exactly once.

During the whole travel, all roads of the country must be passed through exactly twice.

The amount that the employee must pay for tolls by him/herself is the maximum total toll incurred in a single day during the travel, except the first day and the last day. The remaining tolls will be covered by the company.

Shik, as an employee of this company, has only one hope for his travel. He hopes that the amount he must pay for tolls by himself will be as small as possible. Please help Shik to design the travel which satisfies his hope.

Constraints

2 < N < 131,072

1 \leq a_i \leq i for all i

0 \leq v_i \leq 131,072

v_i is an integer

The given tree is a full binary tree

Input

The input is given from Standard Input in the following format:

N
a_1 v_1
a_2 v_2
:
a_{N-1} v_{N-1}

Output

Print an integer denoting the minimum amount Shik must pay by himself for tolls incurred during the travel.

Sample Input 1

7
1 1
1 1
2 1
2 1
3 1
3 1

Sample Output 1

4

There are 4 leaves in the tree formed by the cities (cities 4, 5, 6, and 7), so the travel must be 5 days long. There are 4! = 24 possible arrangements of the leaf cities to stay during the travel, but some of them are invalid. For example, (4,5,6,7) and (6,7,5,4) are valid orders, but (5,6,7,4) is invalid because the route passes 4 times through the road connecting city 1 and city 2. The figure below shows the routes of the travel for these arrangements.

For all valid orders, day 3 is the day with the maximum total incurred toll of 4, passing through 4 roads.

Sample Input 2

9
1 2
1 2
3 2
3 2
5 2
5 2
7 2
7 2

Sample Output 2

6

The following figure shows the route of the travel for one possible arrangement of the stayed cities for the solution. Note that the tolls incurred in the first day and the last day are always covered by the company.

Sample Input 3

15
1 2
1 5
3 3
4 3
4 3
6 5
5 4
5 3
6 3
3 2
11 5
11 3
13 2
13 1

Sample Output 3

15

Sample Input 4

3
1 0
1 0

Sample Output 4

0

Solution in C# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Text;
using System.Collections.Generic;
class Solve{
    int N;
    List<int>[] G;
    List<long>[] C;
    long[][] co1;
    long[][] co2;
    public Solve(){}
    StringBuilder sb;
    public static int Main(){
        new Solve().Run();
        return 0;
    }
    void Run(){
        sb = new StringBuilder();
        Calc();
        Console.Write(sb.ToString());
    }
    void Calc(){
        N = int.Parse(Console.ReadLine());
        G = new List<int>[N];
        C = new List<long>[N];
        for(int i=0;i<N;i++){
            G[i] = new List<int>();
            C[i] = new List<long>();
        }
        for(int i=0;i<N-1;i++){
            string[] str = Console.ReadLine().Split(' ');
            G[int.Parse(str[0])-1].Add(i+1);
            C[int.Parse(str[0])-1].Add(int.Parse(str[1]));
        }
        long f = 0;
        long l = 1000000000000;
        while(f != l){
            long c = (f+l)/2;
            if(check(c)){
                l = c;
            }
            else{
                f = c+1;
            }
        }
        sb.Append(f+"\n");
    }
    bool check(long c){
        co1 = new long[N][];
        co2 = new long[N][];
        return dfs(0,c);
    }
    bool dfs(int v,long c){
        if(G[v].Count == 0){
            co1[v] = new long[1];
            co2[v] = new long[1];
            return true;
        }
        else{
            int c1 = G[v][0];
            int c2 = G[v][1];
            if(!dfs(c1,c)){
                return false;
            }
            if(!dfs(c2,c)){
                return false;
            }
            long cost1 = C[v][0];
            long cost2 = C[v][1];
            if(co2[c1][co2[c1].Length-1] + co2[c2][co2[c2].Length-1] + cost1 + cost2 > c){
                return false;
            }
            else{
                long[] co1c1 = new long[co1[c1].Length];
                long[] co2c1 = new long[co2[c1].Length];
                long[] co1c2 = new long[co1[c2].Length];
                long[] co2c2 = new long[co2[c2].Length];
                for(int i=0;i<co1c1.Length;i++){
                    co1c1[i] = co1[c1][i]+cost1;
                    co2c1[i] = co2[c1][i]+cost1;
                }
                for(int i=0;i<co1c2.Length;i++){
                    co1c2[i] = co1[c2][i]+cost2;
                    co2c2[i] = co2[c2][i]+cost2;
                }
                long[] ps = new long[co1c1.Length];
                int s = 0;
                int r = 0;
                for(int i=ps.Length-1;i>=0;i--){
                    long d = co2c1[i];
                    while(s < co2c2.Length && d + co2c2[s] > c){
                        s++;
                    }
                    if(s >= co2c2.Length){
                        r = i+1;
                        break;
                    }
                    ps[i] = co1c2[s];
                }
                List<long> ct1 = new List<long>();
                List<long> ct2 = new List<long>();
                int p = ps.Length-1;
                int q = r;
                bool b1 = true;
                bool b2 = true;
                while(b1 && b2){
                    if(co1c1[q] < ps[p]){
                        if(ct1.Count == 0 || ct2[ct2.Count-1] > ps[q]){
                            ct1.Add(co1c1[q]);
                            ct2.Add(ps[q]);
                        }
                        q++;
                        b1 = q < co1c1.Length;
                    }
                    else{
                        while(p >= r+1 && ps[p] == ps[p-1]){
                            p--;
                        }
                        if((co1c1[q] > ps[p] || co1c1[p] <= ps[q]) && (ct1.Count == 0 || ct2[ct2.Count-1] > co1c1[p])){
                            ct1.Add(ps[p]);
                            ct2.Add(co1c1[p]);
                        }
                        p--;
                        b2 = p >= r;
                    }
                }
                if(b1){
                    while(q < co1c1.Length){
                        if(ct1.Count == 0 || ct2[ct2.Count-1] > ps[q]){
                            ct1.Add(co1c1[q]);
                            ct2.Add(ps[q]);
                        }
                        q++;
                    }
                }
                else{
                    while(p >= r){
                        while(p >= r+1 && ps[p] == ps[p-1]){
                            p--;
                        }
                        if(ct1.Count == 0 || ct2[ct2.Count-1] > co1c1[p]){
                            ct1.Add(ps[p]);
                            ct2.Add(co1c1[p]);
                        }
                        p--;
                    }
                }
                co1[v] = ct1.ToArray();
                co2[v] = ct2.ToArray();
                return true; 
            }
        }
    }
}