#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define PR pair
#define fi first
#define se second
#define mk make_pair
#define pb push_back
#define REP(i, x, y)   for(int i = (int)(x); i <= (int)(y); i++)
#define FOR(i, x, y)   for(int i = (int)(x); i <  (int)(y); i++)
#define PER(i ,x, y)  for(int i = (int)(x); i >= (int)(y); i--)
#define CH	         ch = getchar()
#define Exit(...)    printf(__VA_ARGS__), exit(0)
#define dln()        fprintf(stderr,"\n")
#define dprintf(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef double	  db;
typedef long long LL;
typedef vector<int> VI;
typedef vector<VI > VII;
typedef PR<int,int> PII;
typedef vector<PII> VPI;
const	int inf=2e9;
const	LL Inf=1e10;
const	int P=1e9+7;
const	int N=131075;

inline LL IN(){
	LL x = 0;
	int ch = 0, f = 0;
	for (CH; ch != -1 && (ch < 48 || ch > 57); CH) f = (ch == '-');
	for (; ch >= 48 && ch <= 57; CH) x = (x << 1) + (x << 3) + ch - '0';
	return f ? (-x) : x;
}
template<typename T> inline int chkmin(T &a, const T &b){if(b < a) return a = b, 1; return 0;}
template<typename T> inline int chkmax(T &a, const T &b){if(b > a) return a = b, 1; return 0;}

void renew(int &x, const int &y){
	x += y;
	if(x >= P) x -= P;
	if(x <  0) x += P;
}

int Pow(int x, int y, int p){
	int a = 1;
	for (; y; y >>= 1, x = (LL)x * x %p) if(y & 1) a=(LL)a * x%p;
	return a;
}

LL Lim, dep[N];
int n, w[N];
struct edge{
	int v, pre;
}e[N]; int dex, adj[N];
struct node{
	LL a, b;
};
vector<node> V[N];

int DFS(int u){
	if(!adj[u]){
		V[u].pb((node){dep[u], dep[u]});
		return 1;
	}
	int x = e[adj[u]].v;
	int y = e[e[adj[u]].pre].v;
	if(!DFS(x)) return 0;
	if(!DFS(y)) return 0;
	int sx = V[x].size();
	int sy = V[y].size();
	int j1 = 0, j2 = 0, i1 = 0, i2 = 0;
	LL mn = 1e12;
	while(i1 < sx || i2 < sy){
		if(i1 >= sx){
			while(j1 < sx && V[x][j1].a + V[y][i2].b - (dep[u] << 1) <= Lim) ++ j1; -- j1;
			LL now = (j1 < 0) ? 1e14 : V[x][j1].b;
			if(now < mn){
				mn = now;
				V[u].pb((node){V[y][i2].a, now});
			}
			++ i2;
		}else
		if(i2 >= sy){
			while(j2 < sy && V[y][j2].a + V[x][i1].b - (dep[u] << 1) <= Lim) ++ j2; -- j2;
			LL now = (j2 < 0) ? 1e14 : V[y][j2].b;
			if(now < mn){
				mn = now;
				V[u].pb((node){V[x][i1].a, now});
			}
			++ i1;
		}else{
			if(V[x][i1].a == V[y][i2].a){
				while(j2 < sy && V[y][j2].a + V[x][i1].b - (dep[u] << 1) <= Lim) ++ j2; -- j2;
				LL now1 = (j2 < 0) ? 1e14 : V[y][j2].b;
				while(j1 < sx && V[x][j1].a + V[y][i2].b - (dep[u] << 1) <= Lim) ++ j1; -- j1;
				LL now2 = (j1 < 0) ? 1e14 : V[x][j1].b;
				if(now1 < now2){
					if(now1 < mn) V[u].pb((node){V[x][i1].a, now1});	
				}else{
					if(now2 < mn) V[u].pb((node){V[y][i2].a, now2});
				}
				++ i1;
				++ i2;
			}else
			if(V[x][i1].a <  V[y][i2].a){
				while(j2 < sy && V[y][j2].a + V[x][i1].b - (dep[u] << 1) <= Lim) ++ j2; -- j2;
				LL now = (j2 < 0) ? 1e14 : V[y][j2].b;
				if(now < mn){
					mn = now;
					V[u].pb((node){V[x][i1].a, now});
				}
				++ i1;
			}else{
				while(j1 < sx && V[x][j1].a + V[y][i2].b - (dep[u] << 1) <= Lim) ++ j1; -- j1;
				LL now = (j1 < 0) ? 1e14 : V[x][j1].b;
				if(now < mn){
					mn = now;
					V[u].pb((node){V[y][i2].a, now});
				}
				++ i2;
			}
		}
		if(j1 < 0) j1 = 0;
		if(j2 < 0) j2 = 0;
	}
	return (bool)V[u].size();
}

int check(LL x){
	Lim = x;
	REP(i, 1, n) V[i].clear();
	return DFS(1);
}

void dfs(int x, LL y){
	dep[x] = y;
	for(int i = adj[x]; i; i = e[i].pre) dfs(e[i].v, y + w[e[i].v]);
}

int main(){
	scanf("%d", &n);
	REP(i, 2, n){
		int f = IN();
		e[++dex] = (edge){i, adj[f]}; adj[f] = dex;
		w[i] = IN();
	}
	dfs(1, 0);
	LL l = 0, r = 1e11, aim = r;
	while(l <= r){
		LL md = (l + r) >> 1;
		if(check(md)){
			aim = md;
			r = md - 1;
		}else{
			l = md + 1;
		}
	}
	cout << aim << endl;
	return 0;
}

Measured memory_bytes: 27768