Problem:
Bridge Removal

ICPC islands once had been a popular tourist destination.
For nature preservation, however, the government decided to prohibit entrance to the islands,
and to remove all the man-made structures there.
The hardest part of the project is to remove all the bridges connecting the islands.

There are n islands and n-1 bridges.
The bridges are built so that all the islands are reachable from all the other islands by
crossing one or more bridges.
The bridge removal team can choose any island as the starting point, and can repeat either of the
following steps.

Move to another island by crossing a bridge that is connected to the current island.

Remove one bridge that is connected to the current island, and stay at the same island after the removal.

Of course, a bridge, once removed, cannot be crossed in either direction.
Crossing or removing a bridge both takes time proportional to the length of the bridge.
Your task is to compute the shortest time necessary for removing all the bridges.
Note that the island where the team starts can differ from where the team finishes the work.

Input

The input consists of at most 100 datasets.
Each dataset is formatted as follows.

n

p2 p3 ... pn

d2 d3 ... dn

The first integer n (3 ≤ n ≤ 800) is the number of the islands.
The islands are numbered from 1 to n.
The second line contains n-1 island numbers pi
(1 ≤ pi < i), and tells that for each i
from 2 to n the island i and the island pi are connected by a bridge.
The third line contains n-1 integers di (1 ≤ di ≤ 100,000)
each denoting the length of the corresponding bridge.
That is, the length of the bridge connecting the island i and pi
is di. It takes di units of time to cross the bridge, and
also the same units of time to remove it.

Note that, with this input format, it is assured that all the islands are reachable each other by
crossing one or more bridges.

The input ends with a line with a single zero.

Output

For each dataset, print the minimum time units required to remove all the bridges in a single line.
Each line should not have any character other than this number.

Sample Input

4
1 2 3
10 20 30
10
1 2 2 1 5 5 1 8 8
10 1 1 20 1 1 30 1 1
3
1 1
1 1
0

Output for the Sample Input

80
136
2

Solution in Rust (judge verdict: Accepted)

// ---------- begin Rerooting ----------
struct Rerooting<Edge, Value, Func, Init> {
    size: usize,
    edge: Vec<(usize, usize, Edge, Edge)>,
    init: Init,
    merge: Func,
    phantom: std::marker::PhantomData<Value>,
}

impl<Edge, Value, Func, Init> Rerooting<Edge, Value, Func, Init>
where
    Edge: Clone,
    Value: Clone,
    Func: Fn(&Value, &Value, &Edge) -> Value,
    Init: Fn(usize) -> Value,
{
    fn new(size: usize, init: Init, func: Func) -> Self {
        Rerooting {
            size: size,
            edge: vec![],
            init: init,
            merge: func,
            phantom: std::marker::PhantomData,
        }
    }
    #[allow(dead_code)]
    fn add_edge(&mut self, a: usize, b: usize, cost: Edge) {
        assert!(a < self.size && b < self.size && a != b);
        self.edge.push((a, b, cost.clone(), cost));
    }
    #[allow(dead_code)]
    fn add_edge_bi(&mut self, a: usize, b: usize, x: Edge, y: Edge) {
        assert!(a < self.size && b < self.size && a != b);
        self.edge.push((a, b, x, y));
    }
    fn solve(&self) -> Vec<Value> {
        let mut graph = vec![vec![]; self.size];
        for e in self.edge.iter() {
            graph[e.0].push((e.1, e.2.clone()));
            graph[e.1].push((e.0, e.3.clone()));
        }
        let root = 0;
        let mut topo = Vec::with_capacity(self.size);
        let mut parent = vec![root; self.size];
        let mut parent_edge: Vec<Option<Edge>> = (0..self.size).map(|_| None).collect();
        let mut stack = vec![root];
        while let Some(v) = stack.pop() {
            topo.push(v);
            if let Some(k) = graph[v].iter().position(|e| e.0 == parent[v]) {
                let x = graph[v].remove(k);
                parent_edge[v] = Some(x.1);
            }
            for e in graph[v].iter() {
                parent[e.0] = v;
                stack.push(e.0);
            }
        }
        assert!(topo.len() == self.size);
        let mut down: Vec<Value> = (0..self.size).map(|k| (self.init)(k)).collect();
        for &v in topo.iter().rev() {
            for e in graph[v].iter() {
                down[v] = (self.merge)(&down[v], &down[e.0], &e.1);
            }
        }
        let mut up: Vec<Value> = (0..self.size).map(|k| (self.init)(k)).collect();
        let mut ans = up.clone();
        for &v in topo.iter() {
            if let Some(e) = parent_edge[v].take() {
                up[v] = (self.merge)(&ans[v], &up[v], &e);
            }
            ans[v] = up[v].clone();
            for e in graph[v].iter() {
                ans[v] = (self.merge)(&ans[v], &down[e.0], &e.1);
            }
            if graph[v].is_empty() {
                continue;
            }
            let mut stack = vec![(graph[v].as_slice(), up[v].clone())];
            while let Some((g, val)) = stack.pop() {
                if g.len() == 1 {
                    up[g[0].0] = val;
                } else {
                    let m = g.len() / 2;
                    let (a, b) = g.split_at(m);
                    let mut p = val.clone();
                    for e in a.iter() {
                        p = (self.merge)(&p, &down[e.0], &e.1);
                    }
                    let mut q = val;
                    for e in b.iter() {
                        q = (self.merge)(&q, &down[e.0], &e.1);
                    }
                    stack.push((b, p));
                    stack.push((a, q));
                }
            }
        }
        ans
    }
}
// ---------- end Rerooting ----------
use std::io::*;
use std::str::*;

struct Scanner<R: BufRead> {
    handle: R,
    buffer: String,
    token: Vec<String>,
}

#[allow(dead_code)]
impl<R: BufRead> Scanner<R> {
    fn new(input: R) -> Self {
        Scanner {
            handle: input,
            buffer: String::new(),
            token: Vec::new(),
        }
    }
    fn next<T: FromStr>(&mut self) -> T {
        loop {
            if let Some(s) = self.token.pop() {
                match s.parse::<T>() {
                    Ok(v) => {
                        return v;
                    },
                    _ => panic!("Scanner error"),
                }
            }
            self.buffer.clear();
            self.handle.read_line(&mut self.buffer).ok();
            let mut i = 0;
            for s in self.buffer.split_whitespace().rev() {
                if i >= self.token.len() {
                    self.token.push(String::new());
                }
                self.token[i].clear();
                self.token[i].push_str(s);
                i += 1;
            }
        }
    }
    fn next_chars(&mut self) -> Vec<char> {
        let s: String = self.next();
        s.chars().collect()
    }
}

fn main() {
    let stdin = std::io::stdin();
    let sc = &mut Scanner::new(stdin.lock());
    let out = std::io::stdout();
    let out = &mut std::io::BufWriter::new(out.lock());
    run(sc, out);
}

fn run(sc: &mut Scanner<StdinLock>, out: &mut BufWriter<StdoutLock>) {
    loop {
        let n: usize = sc.next();
        if n == 0 {
            break;
        }
        type Value = (u32, u32);// 戻る、戻らない
        type Edge = u32;
        let init = |_v: usize| -> Value {
            (0, 0)
        };
        let merge = |a: &Value, b: &Value, c: &Edge| -> Value {
            let d = *c;
            if b.0 == 0 {
                (d + a.0, d + a.1)
            } else {
                (a.0 + 3 * d + b.0, std::cmp::min(a.0 + 2 * d + b.1, 3 * d + b.0 + a.1))
            }
        };
        let mut solver = Rerooting::new(n, init, merge);
        let p: Vec<usize> = (1..n).map(|_| sc.next()).collect();
        let d: Vec<u32> = (1..n).map(|_| sc.next()).collect();
        for i in 0..(n - 1) {
            solver.add_edge(i + 1, p[i] - 1, d[i]);
        }
        let ans = solver.solve().into_iter().map(|p| p.1).min().unwrap();
        writeln!(out, "{}", ans).ok();
    }
}