import scala.collection.mutable
import scala.io.StdIn._
object Main extends App {
  val n = readInt
  val longestPathToLeaf = Array.tabulate(n){_ ⇒ 0}
  val longestRootCircuitPath = Array.tabulate(n){ _ ⇒ 0}
  val longestRootCircuitEdge = Array.tabulate(n){ _ ⇒ 0}
  val longestEdge = Array.tabulate(n){_ ⇒ 0}
  val longestCircuit = Array.tabulate(n){_ ⇒ 0}
  val longestCircuitEdge = Array.tabulate(n){_ ⇒ 0}
  val node = Array.tabulate(n){_ ⇒ Nil: List[(Int, Int)]}
  val edgeCount = Array.tabulate(n){_ ⇒ 0}
  for (i ← 1 until n){
    val Array(p, w) = readLine.trim.split(' ').map(_.toInt)
    node(i) ::= (p, w)
    node(p) ::= (i, w)
    edgeCount(i) += 1
    edgeCount(p) += 1
  }
  var queue: mutable.Queue[Int] = mutable.Queue()
  edgeCount.indices.filter(i ⇒ edgeCount(i) == 1).foreach(queue.enqueue(_))
  while(queue.nonEmpty) {
    val current = queue.dequeue()
    edgeCount(current) -= 1
    for ((to, length) ← node(current) if edgeCount(to) != 0) {
      if (longestCircuitEdge(to) < math.max(length, longestEdge(current))) {
        longestCircuitEdge(to) = math.max(length, longestEdge(current))
      }
      if (longestCircuit(to) + longestCircuitEdge(to) < longestCircuit(current) + math.max(length, longestEdge(to))) {
        longestCircuitEdge(to) = math.max(length, longestEdge(to))
        longestCircuit(to) = longestCircuit(current)
      }
      if (longestCircuit(to) + longestCircuitEdge(to) < longestCircuit(current) + longestCircuitEdge(current)){
        longestCircuitEdge(to) = longestCircuitEdge(current)
        longestCircuit(to) = longestCircuit(current)
      }
      if (longestCircuit(to) + longestCircuitEdge(to) < longestPathToLeaf(to) + longestRootCircuitPath(current) + length + longestRootCircuitEdge(current)) {
        longestCircuitEdge(to) = longestRootCircuitEdge(current)
        longestCircuit(to) = longestPathToLeaf(to) + longestRootCircuitPath(current) + length
      }
      if (longestCircuit(to) + longestCircuitEdge(to) < longestRootCircuitPath(to) + longestPathToLeaf(current) + length + longestRootCircuitEdge(to)) {
        longestCircuitEdge(to) =  longestRootCircuitEdge(to)
        longestCircuit(to) = longestRootCircuitPath(to) + longestPathToLeaf(current) + length
      }
      if (longestRootCircuitPath(to) + longestRootCircuitEdge(to) < longestPathToLeaf(to) + math.max(length, longestEdge(current))) {
        longestRootCircuitPath(to) = longestPathToLeaf(to)
        longestRootCircuitEdge(to) = math.max(length, longestEdge(current))
      }
      if (longestRootCircuitPath(to) + longestRootCircuitEdge(to) < longestRootCircuitPath(current) + length + longestRootCircuitEdge(current)) {
        longestRootCircuitPath(to) = longestRootCircuitPath(current) + length
        longestRootCircuitEdge(to) = longestRootCircuitEdge(current)
      }
      if (longestRootCircuitPath(to) + longestRootCircuitEdge(to) < longestPathToLeaf(current) + length + longestEdge(to)) {
        longestRootCircuitPath(to) = longestPathToLeaf(current) + length
        longestRootCircuitEdge(to) = longestEdge(to)
      }
      if (longestEdge(to) < math.max(length, longestEdge(current))) {
        longestEdge(to) = math.max(length, longestEdge(current))
      }
      if (longestPathToLeaf(to) < longestPathToLeaf(current) + length) {
        longestPathToLeaf(to) = longestPathToLeaf(current) + length
      }
      edgeCount(to) -= 1
      if (edgeCount(to) == 1) {
        queue.enqueue(to)
      }
    }
  }
  println((0 until n).map{i ⇒ longestCircuit(i) + longestCircuitEdge(i)}.max)
}



Measured memory_bytes: 198564