// ---------- 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();
    }
}



Measured memory_bytes: 1696