Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

A - Breadth-First Search by Foxpower

Problem Statement

Fox Ciel went to JAG Kingdom by bicycle, but she forgot a place where she parked her bicycle. So she needs to search it from a bicycle-parking area before returning home.

The parking area is formed as a unweighted rooted tree $T$ with $n$ vertices, numbered $1$ through $n$. Each vertex has a space for parking one or more bicycles. Ciel thought that she parked her bicycle near the vertex $1$, so she decided to search it from there by the breadth-first search. That is, she searches it at the vertices in the increasing order of their distances from the vertex $1$. If multiple vertices have the same distance, she gives priority to the vertices in the order of searching at their parents. If multiple vertices have the same parent, she searches at the vertex with minimum number at first.

Unlike a computer, she can't go to a next vertex by random access. Thus, if she goes to the vertex $j$ after the vertex $i$, she needs to walk the distance between the vertices $i$ and $j$. BFS by fox power perhaps takes a long time, so she asks you to calculate the total moving distance in the worst case starting from the vertex $1$.

Input

The input is formatted as follows.

$n$
$p_2$ $p_3$ $p_4$ $\cdots$ $p_n$

The first line contains an integer $n$ ($1 \le n \le 10^5$), which is the number of vertices on the unweighted rooted tree $T$.
The second line contains $n-1$ integers $p_i$ ($1 \le p_i < i$), which are the parent of the vertex $i$.
The vertex $1$ is a root node, so $p_1$ does not exist.

Output

Print the total moving distance in the worst case in one line.

Sample Input 1

4
1 1 2

Output for the Sample Input 1

6

Sample Input 2

4
1 1 3

Output for the Sample Input 2

4

Sample Input 3

11
1 1 3 3 2 4 1 3 2 9

Output for the Sample Input 3

25

Solution in Scala (judge verdict: Accepted)

import scala.collection.mutable
import scala.io.StdIn._
object Main extends App {

  val n = readInt
  if (n != 1) {
    val children = Array.fill(n) {
      Nil: List[Int]
    }
    val parents = Array.fill(n) {
      0
    }
    val childCount = Array.fill(n) {
      0
    }
    for ((p, c) ← readLine.trim.split(' ').map(_.toInt).zipWithIndex.map { case (p, i) ⇒ (p - 1, i + 1) }.reverse) {
      children(p) ::= c
      childCount(p) += 1
      parents(c) = p
    }
    val heights = Array.fill(n) {
      0
    }
    val queue = mutable.Queue[Int](0)
    var path = Nil: List[Int]
    while (queue.nonEmpty) {
      val top = queue.dequeue()
      path ::= top
      for (c ← children(top)) {
        heights(c) = heights(top) + 1
        queue.enqueue(c)
      }
    }
    val trees = Array.tabulate(n) { i ⇒ new PersistentUnionFind[Int](i) }
    val maxHeights = heights.max
    queue.enqueue(childCount.indices.filter(i ⇒ childCount(i) == 0): _*)
    while (queue.nonEmpty) {
      val top = queue.dequeue()
      if (top != 0) {
        trees(top).mergeAt(trees(parents(top)), maxHeights - heights(parents(top)))
        childCount(parents(top)) -= 1
        if (childCount(parents(top)) == 0) {
          queue.enqueue(parents(top))
        }
      }
    }
    val move = path.dropRight(1).zip(path.tail).map {
      case (f, t) ⇒
        heights(f) + heights(t) - (maxHeights - trees(f).mergedTime(trees(t)).get) * 2L
    }
    println(
      move.sum
    )
  }else {
    println(0)
  }

  class PersistentUnionFind[T](val value: T) {
    private var parent = this
    private var time = Int.MaxValue
    private var size = 1
    private def isTop: Boolean = parent == this
    private def top: PersistentUnionFind[T] = {
      if (parent != this) parent.top
      else this
    }
    def findAt(time: Int): PersistentUnionFind[T] = {
      if (time < this.time) {
        this
      }else {
        parent.findAt(time)
      }
    }
    def mergedTime(that: PersistentUnionFind[T]): Option[Int] = {
      var ti = this
      var ta = that
      var t = time
      while(ti != ta && (!ti.isTop || !ta.isTop)) {
        if (ti.time < ta.time){
          t = ti.time
          ti = ti.parent
        }else {
          t = ta.time
          ta = ta.parent
        }
      }
      if (ti == ta) Some(t)
      else None
    }
    def mergeAt(that: PersistentUnionFind[T], time: Int): Unit = {
      val ti = top
      val ta = that.top
      if (ti != ta){
        if (ti.size < ta.size){
          ti.parent = ta
          ti.time = time
          ta.size += ti.size
        }else {
          ta.parent = ti
          ta.time = time
          ti.size += ta.size
        }
      }
    }
  }
  implicit class Extension[T](val value: T) extends AnyVal {
    @inline def let[A](@inline func: T ⇒ A): A = func(value)
  }
}