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
p
2
p
3
...
p
n
d
2
d
3
...
d
n
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
p
i
(1 ≤
p
i
<
i
), and tells that for each
i
from 2 to
n
the island
i
and the island
p
i
are connected by a bridge.
The third line contains
n
-1 integers
d
i
(1 ≤
d
i
≤ 100,000)
each denoting the length of the corresponding bridge.
That is, the length of the bridge connecting the island
i
and
p
i
is
d
i
. It takes
d
i
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

Submitted solutions:

code_snippet: #include <stdio.h>
#include <vector>
#define MAX 810

int n, p[MAX], d[MAX], check[MAX];
int val, answer=2147483647;
struct data{
	int go, dis;
};
std::vector<data> vec[MAX];
int dy[MAX][2];

void reset(void){
	int i;
	answer=2147483647;
	for (i=1;i<=n;i++){
		vec[i].clear();
	}
}

int max(int a, int b){
	return (a>b) ? a : b;
}
int min(int a, int b){
	return (a<b) ? a : b;
}

int dfs(int now, int root){
	int i, s, ret=0, t, minus=0;
	data chd;
	check[now]=1;
	s=vec[now].size();
	for (i=0;i<s;i++){
		chd=vec[now][i];
		if (check[chd.go]) continue;
		t=dfs(chd.go, root);
		if (t==0) ret+=chd.dis;
		else{
			ret+=chd.dis*3+t;
			if (minus<chd.dis+t-min(dy[chd.go][0], dy[chd.go][1])){
				minus=chd.dis+t-min(dy[chd.go][0], dy[chd.go][1]);
			}
		}
	}
	dy[now][1]=ret;
	for (i=0;i<s;i++){
		chd=vec[now][i];
		if (check[chd.go]) continue;
		if (ret-minus<dy[now][1] && minus!=100000000) dy[now][1]=ret-minus;
	}
	dy[now][0]=ret;
	check[now]=0;
	return dy[now][0];
}

int main(void){
	int i, r;
	data tmp;
	for (;;){
		scanf("%d", &n);
		if (n==0) break;
		for (i=2;i<=n;i++) scanf("%d", &p[i]);
		for (i=2;i<=n;i++){
			scanf("%d", &d[i]);
			tmp.go=p[i], tmp.dis=d[i];
			vec[i].push_back(tmp);
			tmp.go=i;
			vec[p[i]].push_back(tmp);
		}

		for (r=1;r<=n;r++){
			val=dfs(r, r);
			if (min(dy[r][0],dy[r][1])<answer) answer=min(dy[r][0],dy[r][1]);
			for (i=1;i<=n;i++){
				dy[i][0]=dy[i][1]=0;
			}
		}
		printf("%d\n", answer);
		reset();
	}
	return false;
}
accuracy: 1
time_ms: 260
memory_kb: 3104
final_rank: 1

code_snippet: //#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,n) for (ll i=0;i<(ll)n;i++)
#define rrep(i,n) for (ll i=n-1;i>=(ll)0;i--)
#define loop(i,m,n) for(ll i=m;i<=(ll)n;i++)
#define rloop(i,m,n) for(ll i=m;i>=(ll)n;i--)
#define vl vector<ll>
#define vvl vector<vector<ll>>
#define vdbg(a) rep(ii,a.size()){cout<<a[ii]<<" ";}cout<<endl;
#define vpdbg(a) rep(ii,a.size()){cout<<"{"<<a[ii].first<<","<<a[ii].second<<"} ";}cout<<endl;
#define vvdbg(a) rep(ii,a.size()){rep(jj,a[ii].size()){cout<<a[ii][jj]<<" ";}cout<<endl;}
#define setdbg(a) for(const auto & ii:a){cout<<ii<<" ";}cout<<endl;
#define inf 1e9
#define mod 998244353LL
//#define mod 1000000007LL
#define eps 0.000000001
random_device rnd;// 非決定的な乱数生成器
mt19937 mt(rnd());// メルセンヌ・ツイスタの32ビット版、引数は初期シード

//#include<boost/multiprecision/cpp_int.hpp>
//#define bbi boost::multiprecision::cpp_int
//#include<atcoder/lazysegtree>


//整数同士の累乗の計算をする。
ll power(ll A, ll B) {
	ll result = 1;
	for (ll i=0;i<B;i++){
		result *= A;
	}
	return result;
}

// nのk乗をmodで割った余りを計算
ll power_mod(ll n, ll k){
	long long result = 1;
	while (k > 0){
		if ((k&1) ==1)result=(result*n)%mod;
		n=n*n%mod;
		k >>= 1;
	}
	return result;
}


//受け取った2次元文字の外側に、文字pをコーティングする。
vector<string> pad(vector<string> &s,char p){
	ll h=s.size();
	ll w=s[0].size();
	vector<string> res(h+2,string(w+2,p));
	rep(i,h)rep(j,w)res[i+1][j+1]=s[i][j];
	return res;
}

// Union-Find
struct UnionFind {
	vector<int> par, siz;
	UnionFind(int n) : par(n, -1) , siz(n, 1) { }
	// 根を求める
	int root(int x) {
		if (par[x] == -1) return x;
		else return par[x] = root(par[x]);
	}
	// x と y が同じグループに属するかどうか (根が一致するかどうか)
	bool issame(int x, int y) {
		return root(x) == root(y);
	}
	// x を含むグループと y を含むグループとを併合する
	bool unite(int x, int y) {
		x = root(x), y = root(y);
		if (x == y) return false; 
		if (siz[x] < siz[y]) swap(x, y);
		par[y] = x;
		siz[x] += siz[y];
		return true;
	}
	// x を含むグループのサイズ
	int size(int x) {
		return siz[root(x)];
	}
};


//グリッド問題等用
vl dx={1,0,-1,0};
vl dy={0,1,0,-1};

vl dist;
vector<vector<pair<ll,ll>>> g;

void dfs(ll before,ll node){
	rep(i,g[node].size()){
		if(g[node][i].first==before)continue;
		//次が葉じゃなければ遷移
		if(g[g[node][i].first].size()==1)continue;
		dist[g[node][i].first]=dist[node]+g[node][i].second;
		dfs(node,g[node][i].first);
	}
}

ll solve(){
	ll n;
	cin>>n;
	if(n==0){return 1;}

	dist=vl(n,0);
	g=vector<vector<pair<ll,ll>>>(n);
	
	vl p(n);
	vl d(n);

	ll ans=0;

	loop(i,1,n-1)cin>>p[i],p[i]--;
	loop(i,1,n-1)cin>>d[i];

	loop(i,1,n-1){
		g[i].push_back({p[i],d[i]});
		g[p[i]].push_back({i,d[i]});
		ans+=d[i];
	}

	//葉以外同士辺を全て2回足す
	rep(i,n){
		if(g[i].size()==1)continue;
		rep(j,g[i].size()){
			if(g[g[i][j].first].size()==1)continue;
			ans+=g[i][j].second;
		}
	}

	ll mxi;
	rep(i,n){
		if(g[i].size()==1)continue;
		dfs(-1,i);
		mxi=i;
		break;
	}

	rep(i,n){
		if(g[i].size()==1)continue;
		if(dist[i]>dist[mxi])mxi=i;
	}
	dist=vl(n);
	dfs(-1,mxi);
	rep(i,n){
		if(g[i].size()==1)continue;
		if(dist[i]>dist[mxi])mxi=i;
	}

	ans-=dist[mxi];
	cout<<ans<<endl;
	return 0;
}

//メイン
int main(){
	while(solve()==0);
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3544
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

int diam(vector<vector<pair<int, int>>> G) {
    int N = G.size();
    auto D = [&] (int r) -> vector<int> {
        vector<int> d(N);
        auto dfs = [&] (auto dfs, int u, int p) -> void {
            for (auto [v, w] : G[u]) {
                if (v != p) {
                    d[v] = d[u] + w;
                    dfs(dfs, v, u);
                }
            }
        };
        dfs(dfs, r, -1);
        return d;
    };
    auto d = D(0);
    int r = max_element(d.begin(), d.end()) - d.begin();
    d = D(r);
    return *max_element(d.begin(), d.end());
}

bool solve() {
    int N;
    cin >> N;
    if (N == 0) return false;
    vector<int> P(N), D(N);
    for (int i = 1; i < N; i++) {
        cin >> P[i];
        P[i]--;
    }
    for (int i = 1; i < N; i++) cin >> D[i];
    vector<vector<pair<int, int>>> G(N);
    long long ans = 0;
    for (int i = 1; i < N; i++) {
        G[i].emplace_back(P[i], D[i]);
        G[P[i]].emplace_back(i, D[i]);
        ans += 3 * D[i];
    }
    vector<int> alive;
    for (int i = 0; i < N; i++) {
        if (G[i].size() > 1) alive.push_back(i);
    }
    vector<vector<pair<int, int>>> H(N);
    for (int u = 0; u < N; u++) {
        for (auto [v, w] : G[u]) {
            if (u < v) continue;
            if (G[u].size() > 1 && G[v].size() > 1) {
                int a = lower_bound(alive.begin(), alive.end(), u) - alive.begin();
                int b = lower_bound(alive.begin(), alive.end(), v) - alive.begin();
                H[a].emplace_back(b, w);
                H[b].emplace_back(a, w);
            } else {
                ans -= 2 * w;
            }
        }
    }
    ans -= diam(H);
    cout << ans << '\n';
    return true;
}

int main() {
    while (solve()) {}
}
accuracy: 1
time_ms: 10
memory_kb: 3840
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;

int Diam(vector<vector<pair<int, int>>> G) {
    int N = G.size();
    auto BFS = [&] (int r) -> vector<int> {
        vector<int> D(N, 1 << 30);
        D[r] = 0;
        queue<int> q;
        q.push(r);
        while (q.size()) {
            int u = q.front();
            q.pop();
            for (auto [v, w] : G[u]) {
                if (D[v] > D[u] + w) {
                    D[v] = D[u] + w;
                    q.push(v);
                }
            }
        }
        return D;
    };
    auto D = BFS(0);
    int L = max_element(D.begin(), D.end()) - D.begin();
    D = BFS(L);
    return *max_element(D.begin(), D.end());
}

bool solve() {
    int N;
    cin >> N;
    if (N == 0) return false;
    vector<int> P(N), D(N);
    int ans = 0;
    for (int i = 1; i < N; i++) cin >> P[i], P[i]--;
    for (int i = 1; i < N; i++) cin >> D[i], ans += 3 * D[i];
    vector<vector<pair<int, int>>> G(N);
    for (int i = 1; i < N; i++) {
        G[i].emplace_back(P[i], D[i]);
        G[P[i]].emplace_back(i, D[i]);
    }
    vector<int> alive;
    for (int i = 0; i < N; i++) {
        if (G[i].size() >= 2) alive.push_back(i);
    }
    vector<int> id(N, -1);
    for (int i = 0; i < N; i++) {
        if (G[i].size() >= 2) {
            id[i] = lower_bound(alive.begin(), alive.end(), i) - alive.begin();
        }
    }
    int M = alive.size();
    vector<vector<pair<int, int>>> H(M);
    for (int u = 0; u < N; u++) {
        for (auto [v, d] : G[u]) {
            if (u > v) continue;
            if (G[u].size() >= 2 && G[v].size() >= 2) {
                H[id[u]].emplace_back(id[v], d);
                H[id[v]].emplace_back(id[u], d);
            } else {
                ans -= 2 * d;
            }
        }
    }
    cout << ans - Diam(H) << '\n';
    return true;
}

int main() {
    while (solve()) {}
}
accuracy: 1
time_ms: 10
memory_kb: 3840
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(...) std::begin(__VA_ARGS__), std::end(__VA_ARGS__)
#define rall(...) std::rbegin(__VA_ARGS__), std::rend(__VA_ARGS__)
#define OVERLOAD_REP(_1, _2, _3, _4, name, ...) name
#define REP1(n) for(ll i=0;i<(n);i++)
#define REP2(i, n) for (ll i=0;i<(n);i++)
#define REP3(i, a, n) for (ll i=a;i<(n);i++)
#define REP4(i, a, b, n) for(ll i=a;i<(n);i+=b)
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP4, REP3, REP2, REP1)(__VA_ARGS__)
#define OVERLOAD_RREP(_1, _2, _3, _4, name, ...) name
#define RREP1(n) for(ll i=(n)-1;i>=0;i--)
#define RREP2(i, n) for(ll i=(n)-1;i>=0;i--)
#define RREP3(i, a, n) for(ll i=(n)-1;i>=(a);i--)
#define RREP4(i, a, b, n) for(ll i=(n)-1;i>=(a);i-=(b))
#define rrep(...) OVERLOAD_RREP(__VA_ARGS__, RREP4, RREP3, RREP2, RREP1)(__VA_ARGS__)
#define uniq(a) sort(all(a));a.erase(unique(all(a)),end(a))
#define len(n) (long long)(n).size()
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vs = vector<string>;
using vvs = vector<vs>;
using vvvs = vector<vvs>;
using vld = vector<ld>;
using vvld = vector<vld>;
using vvvld = vector<vvld>;
using vc = vector<char>;
using vvc = vector<vc>;
using vvvc = vector<vvc>;
using pll = pair<ll,ll>;
using vpll = vector<pll>;
using vvpll = vector<vpll>;

ll intpow(ll a,ll b){
    ll ans = 1;
    while (b){
        if (b & 1){
            ans *= a;
        }
        a *= a;
        b /= 2;
    }
    return ans;
}
ll modpow(ll a,ll b,ll c){
    ll ans = 1;
    while (b){
        if (b & 1){
            ans *= a;
            ans %= c;
        }
        a *= a;
        a %= c;
        b /= 2;
    }
    return ans;
}

template<class... T>
void input(T&... a){
    (cin >> ... >> a);
}

#define INT(...) int __VA_ARGS__; input(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define STR(...) string __VA_ARGS__; input(__VA_ARGS__)
#define CHA(...) char __VA_ARGS__; input(__VA_ARGS__)
#define VLL(name,length) vll name(length);rep(i,length){cin >> name[i];}
#define VVLL(name,h,w) vvll name(h,vll(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVLL(name,a,b,c) vvvll name(a,vvll(b,vll(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VI(name,length) vi name(length);rep(i,length){cin >> name[i];}
#define VVI(name,h,w) vvi name(h,vi(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVI(name,a,b,c) vvvi name(a,vvll(b,vi(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VLD(name,length) vld name(length);rep(i,length){cin >> name[i];}
#define VVLD(name,h,w) vvld name(h,vld(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVLD(name,a,b,c) vvvld name(a,vvld(b,vld(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VC(name,length) vc name(length);rep(i,length){cin >> name[i];}
#define VVC(name,h,w) vvc name(h,vc(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVC(name,a,b,c) vvvc name(a,vvc(b,vc(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define VS(name,length) vs name(length);rep(i,length){cin >> name[i];}
#define VVS(name,h,w) vvs name(h,vs(w));rep(i,h)rep(j,w){cin >> name[i][j];}
#define VVVS(name,a,b,c) vvvs name(a,vvs(b,vs(c)));rep(i,a)rep(j,b)rep(k,c){cin >> name[i][j][k];}
#define PLL(name) pll name;cin>>name.first>>name.second;
#define VPLL(name,length) vpll name(length);rep(i,length){cin>>name[i].first>>name[i].second;}

void print(){cout << "\n";}

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p) {
    os << "(" << p.first << ", " << p.second << ")";
    return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {
    os << "[";
    for (size_t i = 0; i < vec.size(); ++i) {
        os << vec[i];
        if (i + 1 < vec.size()) os << ", ";
    }
    os << "]";
    return os;
}

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::vector<std::pair<T1, T2>>& a) {
    os << "[";
    for (size_t j = 0; j < a.size(); ++j) {
        os << "(" << a[j].first << ", " << a[j].second << ")";
		if (j + 1 < a.size()) os << ", ";
    }
	os << "]";
    return os;
}

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<std::pair<T1, T2>>>& mat) {
	os << "[";
    for (size_t i = 0; i < mat.size(); ++i) {
		os << "[";
        for (size_t j = 0; j < mat[i].size(); ++j) {
            os << "(" << mat[i][j].first << ", " << mat[i][j].second << ")";
			if (j + 1 < mat[i].size()) os << ", ";
        }
		os << "]";
		if (i + 1 < mat.size()) os << ", ";
    }
	os << "]";
    return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& s) {
    os << "{";
    bool first = true;
    for (const auto& x : s) {
        if (!first) os << ", ";
        os << x;
        first = false;
    }
    os << "}";
    return os;
}

template <typename K, typename V>
std::ostream& operator<<(std::ostream& os, const std::map<K, V>& m) {
    os << "{";
    bool first = true;
    for (const auto& [key, val] : m) {
        if (!first) os << ", ";
        os << key << ": " << val;
        first = false;
    }
    os << "}";
    return os;
}

template<class T, class... Ts>
void print(const T& a, const Ts&... b){cout << a;(cout << ... << (cout << ' ', b));cout << '\n';}

void write(){cout << "\n";}
template<class T, class... Ts>
void write(const T& a, const Ts&... b){cout << a;(cout << ... << (cout << ' ', b));cout << '\n';}
void write(vll x){rep(i,len(x)){cout << x[i];if(i!=len(x)-1){cout << " ";}else{cout << '\n';}}}
void write(vvll x){rep(i,len(x))rep(j,len(x[i])){cout << x[i][j];if(j!=len(x[i])-1){cout << " ";}else{cout << '\n';}}}
void write(vi x){rep(i,len(x)){cout << x[i];if(i!=len(x)-1){cout << " ";}else{cout << '\n';}}}
void write(vvi x){rep(i,len(x))rep(j,len(x[i])){cout << x[i][j];if(j!=len(x[i])-1){cout << " ";}else{cout << '\n';}}}
void write(vvvi x){rep(i,len(x))rep(j,len(x[i]))rep(k,len(x[i][j])){cout << x[i][j][k];if(k!=len(x[i][j])-1){cout << " ";}else if(j!=len(x[i])-1){cout << " | ";}else{cout << '\n';}}}
void write(vld x){rep(i,len(x)){cout << x[i];if(i!=len(x)-1){cout << " ";}else{cout << '\n';}}}
void write(vvld x){rep(i,len(x))rep(j,len(x[i])){cout << x[i][j];if(j!=len(x[i])-1){cout << " ";}else{cout << '\n';}}}
void write(vvvld x){rep(i,len(x))rep(j,len(x[i]))rep(k,len(x[i][j])){cout << x[i][j][k];if(k!=len(x[i][j])-1){cout << " ";}else if(j!=len(x[i])-1){cout << " | ";}else{cout << '\n';}}}
void write(vc x){rep(i,len(x)){cout << x[i];if(i!=len(x)-1){cout << " ";}else{cout << '\n';}}}
void write(vvc x){rep(i,len(x))rep(j,len(x[i])){cout << x[i][j];if(j!=len(x[i])-1){cout << " ";}else{cout << '\n';}}}
void write(vvvc x){rep(i,len(x))rep(j,len(x[i]))rep(k,len(x[i][j])){cout << x[i][j][k];if(k!=len(x[i][j])-1){cout << " ";}else if(j!=len(x[i])-1){cout << " | ";}else{cout << '\n';}}}
void write(vs x){rep(i,len(x)){cout << x[i];if(i!=len(x)-1){cout << " ";}else{cout << '\n';}}}
void write(vvs x){rep(i,len(x))rep(j,len(x[i])){cout << x[i][j];if(j!=len(x[i])-1){cout << " ";}else{cout << '\n';}}}
void write(vvvs x){rep(i,len(x))rep(j,len(x[i]))rep(k,len(x[i][j])){cout << x[i][j][k];if(k!=len(x[i][j])-1){cout << " ";}else if(j!=len(x[i])-1){cout << " | ";}else{cout << '\n';}}}
void write(pll x){cout << x.first << ' ' << x.second << '\n';}
void write(vpll x){rep(i,len(x)){cout << x[i].first << ' ' << x[i].second << '\n';}}
void write(vvpll x){rep(i,len(x))rep(j,len(x[i])){cout << x[i][j].first << ' ' << x[i][j].second;if(j!=len(x[i])-1){cout << " ";}else{cout << '\n';}}}

template <typename T>
T sum(const std::vector<T>& v) {
    return std::accumulate(v.begin(), v.end(), T(0));
}

template<class T> bool chmin(T& a, const T& b){ if(a > b){ a = b; return 1; } return 0; }
template<class T> bool chmax(T& a, const T& b){ if(a < b){ a = b; return 1; } return 0; }
template<class T, class U> bool chmin(T& a, const U& b){ if(a > T(b)){ a = b; return 1; } return 0; }
template<class T, class U> bool chmax(T& a, const U& b){ if(a < T(b)){ a = b; return 1; } return 0; }

long long mod_mul(long long a, long long b, long long mod) {
    return (__int128)a * b % mod;
}

long long mod_pow(long long a, long long b, long long mod) {
    long long result = 1;
    a %= mod;
    while (b > 0) {
        if (b & 1) result = mod_mul(result, a, mod);
        a = mod_mul(a, a, mod);
        b >>= 1;
    }
    return result;
}

bool MillerRabin(ll x){
    
    if(x <= 1){return false;}
    if(x == 2){return true;}
    if((x & 1) == 0){return false;}
    vll test;
    if(x < (1 << 30)){
        test = {2, 7, 61};
    } 
    else{
        test = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
    }
    ll s = 0;
    ll d = x - 1;
    while((d & 1) == 0){
        s++;
        d >>= 1;
    }
    for(ll i:test){
        if(x <= i){return true;}
        ll y = mod_pow(i,d,x);
        if(y == 1 || y == x - 1){continue;}
        ll c = 0;
        for(int j=0;j<s-1;j++){
            y = mod_mul(y,y,x);
            if(y == x - 1){
                c = 1;
                break;
            }
        }
        if(c == 0){
            return false;
        }
    }
    return true;
}

#include<atcoder/dsu>
vpll rle(vll seq){
    vpll res;
    for(auto x:seq){
        if(res.empty() || res.back().first != x){
            res.emplace_back(x,1);
        }
        else{
            res.back().second++;
        }
    }
    return res;
}
int main(){
	ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
    
    while(1){
        LL(n);
        if(n == 0){break;}
        VLL(p,n-1);
        VLL(d,n-1);
        vvpll edge(n);
        vll deg(n,0);
        rep(i,n-1){
            edge[i+1].emplace_back(p[i]-1,d[i]);
            edge[p[i]-1].emplace_back(i+1,d[i]);
            deg[i+1]++;
            deg[p[i]-1]++;
            //print(i+1,p[i]-1,d[i]);
        }
        ll ans = 1LL<<60;
        vll dp1(n,1LL<<60);
        vll dp2(n,1LL<<60);
        auto dfs = [&](auto dfs, ll now, ll pa) -> void{
            dp1[now] = 0;
            vll a;
            vll b;
            for(auto [to,cost]:edge[now]){
                if(to == pa){
                    continue;
                }
                if(deg[to] == 1){
                    dp1[to] = 0;
                    dp2[to] = 0;
                    a.push_back(dp1[to]);
                    b.push_back(dp2[to]);
                    continue;
                }
                dfs(dfs,to,now);
                a.push_back(dp1[to] + 2 * cost);
                b.push_back(dp2[to] + 1 * cost);
                dp1[now] += dp1[to] + 2 * cost;
            }
            ll c = 1LL<<60;;
            rep(i,len(a)){
                chmin(c,-a[i]+b[i]);
            }
            dp2[now] = sum(a) + c;
            return;
            ll x = 0;
            rep(i,len(a)){
                ll temp = 0;
                rep(j,len(a)){
                    temp += (i == j? b[j]:a[j]);
                }
                chmin(dp2[now],temp);
            }
            
        };

        rep(i,n){
            rep(j,n){
                dp1[j] = 1LL<<60;
                dp2[j] = 1LL<<60;
                
            }
            dfs(dfs,i,-1);
            chmin(ans,dp2[i]);
            //print(i,dp2[i] + sum(d),dp1,dp2);
        }
        print(ans + sum(d));
        //print(edge);
    }
    
}
accuracy: 1
time_ms: 970
memory_kb: 3840
final_rank: 20

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll   = long long;
using edge = pair<int, int>; // {to, cost}

constexpr int INF    = 1e9;
constexpr bool DEBUG = false;

vector<int> bfs(const int& n, const int& start_vertex, const vector<vector<edge>>& graph) {
    vector<int> dist(n, INF);
    queue<int> q;
    dist[start_vertex] = 0;
    q.push(start_vertex);

    while (!q.empty()) {
        const int from = q.front();
        q.pop();
        for (auto& [to, cost] : graph[from]) {
            if (dist[to] == INF) {
                dist[to] = dist[from] + cost;
                q.push(to);
            }
        }
    }

    return dist;
}

int solve(const int& n, const vector<int>& p, const vector<int>& d) {
    // グラフの作成
    int rm_cost = 0;
    vector<int> deg(n, 0);
    vector<vector<edge>> graph(n);
    for (int i = 0; i < n - 1; i++) {
        int u = i + 1;
        int v = p[i];
        int w = d[i];
        graph[u].emplace_back(v, w);
        graph[v].emplace_back(u, w);
        deg[u]++;
        deg[v]++;
        rm_cost += w;
    }

    // 葉を除いたグラフ作成
    int g_cost = 0;
    vector<vector<edge>> g(n);
    for (int i = 0; i < n - 1; i++) {
        int u = i + 1;
        int v = p[i];
        int w = d[i];
        if (deg[u] > 1 && deg[v] > 1) {
            g[u].emplace_back(v, w);
            g[v].emplace_back(u, w);
            g_cost += w;
        }
    }

    // 木の直径を求める
    int start_v = -1;
    for (int i = 0; i < n; i++) {
        if (deg[i] > 1) {
            start_v = i;
        }
    }
    const auto dist1 = bfs(n, start_v, g);

    int far_v = start_v;
    for (int i = 0; i < n; i++) {
        if (dist1[i] != INF && dist1[i] > dist1[far_v]) {
            far_v = i;
        }
    }
    const auto dist2 = bfs(n, far_v, g);

    int D = 0;
    for (int i = 0; i < n; i++) {
        if (dist2[i] != INF && dist2[i] > D) {
            D = dist2[i];
        }
    }

    // 答えを求める: 橋を取り除くコスト + 移動コスト(葉を除いたグラフの辺の総和*2 - 直径)
    const int mv_cost = g_cost * 2 - D;
    const int ret     = rm_cost + mv_cost;
    if (DEBUG) {
        printf("%d+%d(2*%d-%d)=%d\n", rm_cost, mv_cost, g_cost, D, ret);
    }
    return ret;
}

int main() {
    while (true) {
        int n;
        cin >> n;
        if (n == 0) {
            break;
        }

        vector<int> p(n - 1);
        vector<int> d(n - 1);
        for (auto& pi : p) {
            cin >> pi;
            pi--;
        }
        for (auto& di : d) {
            cin >> di;
        }
        cout << solve(n, p, d) << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3584
final_rank: 7

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll   = long long;
using edge = pair<int, int>; // {to, cost}

constexpr int INF    = 1e9;
constexpr bool DEBUG = false;

vector<int> bfs(const int& n, const int& start_vertex, const vector<vector<edge>>& graph) {
    vector<int> dist(n, INF);
    queue<int> q;
    dist[start_vertex] = 0;
    q.push(start_vertex);

    while (!q.empty()) {
        const int from = q.front();
        q.pop();
        for (auto& [to, cost] : graph[from]) {
            if (dist[to] == INF) {
                dist[to] = dist[from] + cost;
                q.push(to);
            }
        }
    }

    return dist;
}

int solve(const int& n, const vector<int>& p, const vector<int>& d) {
    // グラフの作成
    int rm_cost = 0;
    vector<int> deg(n, 0);
    vector<vector<edge>> graph(n);
    for (int i = 0; i < n - 1; i++) {
        int u = i + 1;
        int v = p[i];
        int w = d[i];
        graph[u].emplace_back(v, w);
        graph[v].emplace_back(u, w);
        deg[u]++;
        deg[v]++;
        rm_cost += w;
    }

    // 木の直径を求める(葉は考慮しない)
    int g_cost = 0;
    vector<vector<edge>> g(n);
    for (int i = 0; i < n - 1; i++) {
        int u = i + 1;
        int v = p[i];
        int w = d[i];
        if (deg[u] > 1 && deg[v] > 1) {
            g[u].emplace_back(v, w);
            g[v].emplace_back(u, w);
            g_cost += w;
        }
    }

    int start_v = -1;
    for (int i = 0; i < n; i++) {
        if (deg[i] > 1) {
            start_v = i;
        }
    }
    const auto dist1 = bfs(n, start_v, g);

    int far_v = start_v;
    for (int i = 0; i < n; i++) {
        if (dist1[i] != INF && dist1[i] > dist1[far_v]) {
            far_v = i;
        }
    }
    const auto dist2 = bfs(n, far_v, g);

    int D = 0;
    for (int i = 0; i < n; i++) {
        if (dist2[i] != INF && dist2[i] > D) {
            D = dist2[i];
        }
    }

    // 答えを求める: 橋を取り除くコスト + 移動コスト(葉を除いたグラフのコストの総和*2 - 直径)
    const int mv_cost = g_cost * 2 - D;
    const int ret     = rm_cost + mv_cost;
    if (DEBUG) {
        printf("%d+%d(2*%d-%d)=%d\n", rm_cost, mv_cost, g_cost, D, ret);
    }
    return ret;
}

int main() {
    while (true) {
        int n;
        cin >> n;
        if (n == 0) {
            break;
        }

        vector<int> p(n - 1);
        vector<int> d(n - 1);
        for (auto& pi : p) {
            cin >> pi;
            pi--;
        }
        for (auto& di : d) {
            cin >> di;
        }
        cout << solve(n, p, d) << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3712
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll   = long long;
using edge = pair<int, int>; // {to, cost}

constexpr int INF = 1e9;

vector<int> bfs(const int& n, const int& start_vertex, const vector<vector<edge>>& graph) {
    vector<int> dist(n, INF);
    queue<int> q;
    dist[start_vertex] = 0;
    q.push(start_vertex);

    while (!q.empty()) {
        const int from = q.front();
        q.pop();
        for (auto& [to, cost] : graph[from]) {
            if (dist[to] == INF) {
                dist[to] = dist[from] + cost;
                q.push(to);
            }
        }
    }

    return dist;
}

int solve(const int& n, const vector<int>& p, const vector<int>& d) {
    // グラフの作成
    int rm_cost = 0;
    vector<int> deg(n, 0);
    vector<vector<edge>> graph(n);
    for (int i = 0; i < n - 1; i++) {
        int u = i + 1;
        int v = p[i];
        int w = d[i];
        graph[u].emplace_back(v, w);
        graph[v].emplace_back(u, w);
        deg[u]++;
        deg[v]++;
        rm_cost += w;
    }

    // 木の直径を求める(葉は考慮しない)
    int g_cost = 0;
    vector<vector<edge>> g(n);
    for (int i = 0; i < n - 1; i++) {
        int u = i + 1;
        int v = p[i];
        int w = d[i];
        if (deg[u] > 1 && deg[v] > 1) {
            g[u].emplace_back(v, w);
            g[v].emplace_back(u, w);
            g_cost += w;
        }
    }


    int start_v = -1;
    for (int i = 0; i < n; i++) {
        if (deg[i] > 1) {
            start_v = i;
        }
    }
    const auto dist1 = bfs(n, start_v, g);

    int far_v = start_v;
    for (int i = 0; i < n; i++) {
        if (dist1[i] != INF && dist1[i] > dist1[far_v]) {
            far_v = i;
        }
    }
    const auto dist2 = bfs(n, far_v, g);

    int D = 0;
    for (int i = 0; i < n; i++) {
        if (dist2[i] != INF && dist2[i] > D) {
            D = dist2[i];
        }
    }

    // 答えを求める: 橋を取り除くコスト + 移動コスト(葉を除いたグラフのコストの総和*2 - 直径)
    const int mv_cost = g_cost * 2 - D;
    const int ret     = rm_cost + mv_cost;
    // printf("%d+%d(2*%d-%d)=%d\n", rm_cost, mv_cost, g_cost, D, ret);
    return ret;
}

int main() {
    while (true) {
        int n;
        cin >> n;
        if (n == 0) {
            break;
        }

        vector<int> p(n - 1);
        vector<int> d(n - 1);
        for (auto& pi : p) {
            cin >> pi;
            pi--;
        }
        for (auto& di : d) {
            cin >> di;
        }
        cout << solve(n, p, d) << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3712
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll   = long long;
using edge = pair<int, int>; // {to, cost}

constexpr int INF = 1e9;

vector<int> bfs(const int& n, const int& start_vertex, const vector<vector<edge>>& graph) {
    vector<int> dist(n, INF);
    queue<int> q;
    dist[start_vertex] = 0;
    q.push(start_vertex);

    while (!q.empty()) {
        const int from = q.front();
        q.pop();
        for (auto& [to, cost] : graph[from]) {
            if (dist[to] == INF) {
                dist[to] = dist[from] + cost;
                q.push(to);
            }
        }
    }

    return dist;
}

int solve(const int& n, const vector<int>& p, const vector<int>& d) {
    // グラフの作成
    vector<int> deg(n, 0);
    vector<vector<edge>> graph(n);
    for (int i = 1; i < n; i++) {
        graph[i].emplace_back(p[i - 1], d[i - 1]);
        graph[p[i - 1]].emplace_back(i, d[i - 1]);
        deg[i]++;
        deg[p[i - 1]]++;
    }

    // 木の直径を求める(葉は考慮しない)
    vector<vector<edge>> g(n);
    for (int i = 0; i < n - 1; i++) {
        int u = i + 1;
        int v = p[i];
        int w = d[i];
        if (deg[u] > 1 && deg[v] > 1) {
            g[u].emplace_back(v, w);
            g[v].emplace_back(u, w);
        }
    }


    int start_v = -1;
    for (int i = 0; i < n; i++) {
        if (deg[i] > 1) {
            start_v = i;
        }
    }
    const auto dist1 = bfs(n, start_v, g);

    int far_v = start_v;
    for (int i = 0; i < n; i++) {
        if (dist1[i] != INF && dist1[i] > dist1[far_v]) {
            far_v = i;
        }
    }
    const auto dist2 = bfs(n, far_v, g);

    int D = 0;
    for (int i = 0; i < n; i++) {
        if (dist2[i] != INF && dist2[i] > D) {
            D = dist2[i];
        }
    }

    // 答えを求める: 橋を取り除くコスト + 移動コスト(葉を除いたグラフのコストの総和*2 - 直径)
    int rm_cost = 0;
    for (auto& di : d) {
        rm_cost += di;
    }

    int g_cost = 0;
    for (int i = 0; i < n - 1; i++) {
        const int u = i + 1;
        const int v = p[i];
        if (deg[u] > 1 && deg[v] > 1) {
            g_cost += d[i];
        }
    }

    const int mv_cost = g_cost * 2 - D;
    const int ret     = rm_cost + mv_cost;
    // printf("%d+%d(2*%d-%d)=%d\n", rm_cost, mv_cost, g_cost, D, ret);
    return ret;
}

int main() {
    while (true) {
        int n;
        cin >> n;
        if (n == 0) {
            break;
        }

        vector<int> p(n - 1);
        vector<int> d(n - 1);
        for (auto& pi : p) {
            cin >> pi;
            pi--;
        }
        for (auto& di : d) {
            cin >> di;
        }
        cout << solve(n, p, d) << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3712
final_rank: 12

code_snippet: #include <bits/stdc++.h>
    using namespace std;
    
    template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
    template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
    #define rep(i,n) for (int i = 0; i < (n); ++i)

    typedef long long ll;
    typedef unsigned long long ull;
    using P=pair<int,int>;
    using T=tuple<ll,ll,ll>;
    const int INF=1001001001;
    const ll INFL=1e18;
    const int mod=998244353;
	
	void dfs(int v,int pre,vector<int>& mx,vector<vector<P>>& G){
		for(auto[u,w]:G[v]){
			if(u==pre)continue;
			dfs(u,v,mx,G);
			chmax(mx[v],mx[u]+w);
		}
	}

    bool solve(){
		int n;
		cin>>n;
		if(!n)return false;
		vector<int>a(n),b(n),deg(n);
		rep(i,n-1){
			cin>>a[i];
			a[i]--;
			deg[a[i]]++;deg[i+1]++;
		}
		rep(i,n-1){cin>>b[i];}
		
		vector<vector<P>>G(n);
		int tot=0;
		rep(i,n-1){
			if(deg[a[i]]>1&&deg[i+1]>1){
				tot+=b[i]*3;
				G[i+1].push_back({a[i],b[i]});
				G[a[i]].push_back({i+1,b[i]});
			}else{
				tot+=b[i];
			}
		}
		
		int ans=INF;
		rep(i,n){
			vector<int>mx(n);
			dfs(i,-1,mx,G);
			chmin(ans,tot-mx[i]);
		}
		cout<<ans<<endl;
		
		return true;
    }

    int main(){
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);

		while(1){
			if(!solve()){break;}
		}
		
        return 0;
    }
accuracy: 1
time_ms: 80
memory_kb: 3584
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int Diam(int N, int S, vector<vector<pair<int,int>>>& G) {
    vector<int> DP(N,inf);
    queue<int> Q;
    DP[S] = 0;
    Q.push(S);
    while(!Q.empty()) {
        int P = Q.front();
        Q.pop();
        for (pair<int,int> E : G[P]) {
            if (DP[E.first] == inf) {
                DP[E.first] = DP[P] + E.second;
                Q.push(E.first);
            }
        }
    }
    int NS = -1, MAX = -1;
    rep(i,0,N) {
        if (DP[i] == inf) continue;
        if (DP[i] > MAX) {
            MAX = DP[i], NS = i;
        }
    }
    DP.assign(N,inf);
    DP[NS] = 0;
    Q.push(NS);
    while(!Q.empty()) {
        int P = Q.front();
        Q.pop();
        for (pair<int,int> E : G[P]) {
            if (DP[E.first] == inf) {
                DP[E.first] = DP[P] + E.second;
                Q.push(E.first);
            }
        }
    }
    int Ret = -1;
    rep(i,0,N) {
        if (DP[i] == inf) continue;
        chmax(Ret, DP[i]);
    }
    return Ret;
}

int main() {
while(1) {
    int N;
    cin >> N;
    if (N == 0) return 0;
    vector<int> P(N,-1), D(N,0);
    vector<vector<pair<int,int>>> G(N);
    rep(i,1,N) cin >> P[i], P[i]--;
    rep(i,1,N) cin >> D[i];
    int ANS = 0;
    rep(i,1,N) {
        G[P[i]].push_back({i,D[i]});
        G[i].push_back({P[i],D[i]});
        ANS += D[i] * 3;
    }
    vector<int> S(N);
    rep(i,0,N) S[i] = G[i].size();
    rep(i,0,N) {
        if (S[i] == 1) {
            ANS -= G[i][0].second * 2;
        }
    }
    vector<vector<pair<int,int>>> NG(N);
    rep(i,0,N) {
        if (S[i] == 1) continue;
        for (pair<int,int> P : G[i]) {
            if (S[P.first] == 1) continue;
            NG[i].push_back(P);
        }
    }
    rep(i,0,N) {
        if (!NG[i].empty()) {
            ANS -= Diam(N,i,NG);
            break;
        }
    }
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 10
memory_kb: 3620
final_rank: 8

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using P = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,n) for(ll i = 0;i < (ll)n;i++)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}

// verify 木DP https://atcoder.jp/contests/dp/submissions/55190036
// verify 全方位木DP(直径) https://onlinejudge.u-aizu.ac.jp/status/users/shkii/submissions/1/GRL_5_A/judge/9411502/C++17
// verify 全方位木DP https://atcoder.jp/contests/arc179/submissions/55189994
tuple<vector<int>,vector<int>,vector<int>> tree_dfs(vector<vector<int>> &v,int root = 0){
  int n = v.size();
  vector<int> par(n,-1); // par[i] := rootを根とした頂点iの親
  vector<int> par_idx(n,-1); // par_idx[ov] := v[ov]の中でpar[ov]がいるidx
  vector<int> order(n,-1); // order[i] := dfs帰りがけ順i番目の頂点。この昇順に木DP そのあと降順に全方位木DP
  int cnt = 0;
  auto dfs = [&](auto &dfs,int ov,int pre)->void{
    par[ov] = pre;
    for(int i = 0;i < v[ov].size();i++){
      int nv = v[ov][i];
      if(nv == pre){
        par_idx[ov] = i;
        continue;
      }
      dfs(dfs,nv,ov);
    }
    order[cnt++] = ov;
  };
  dfs(dfs,root,-1);
  return {par,par_idx,order};
};


int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  while(1){
    int n;cin >> n;
    if(!n)break;
    vi p(n-1),d(n-1);
    cin >> p >> d;
    vi cnt(n);
    ll res = 0;
    rep(i,n-1){
      p[i]--;
      cnt[p[i]]++;cnt[i+1]++;
      res += d[i];
    }
    ve v(n);
    vvi w(n);
    int root = 0;
    rep(i,n-1){
      if(cnt[i+1] != 1 && cnt[p[i]] != 1){
        v[i+1].emplace_back(p[i]);
        v[p[i]].emplace_back(i+1);
        w[i+1].emplace_back(d[i]);
        w[p[i]].emplace_back(d[i]);
        res += 2*d[i];
      }
    }
    rep(i,n)if(cnt[i] != 1)root = i;
    vvi dp(n);
    auto [par,p_idx,ord] = tree_dfs(v,root);
    auto f = [](ll a,ll c,ll w){return max(a,c+w);};
    auto g = [](ll a,ll b){return max(a,b);};
    rep(_,n){
      int ov = ord[_];
      if(ov == -1)break;
      int deg = sz(v[ov]);
      dp[ov].resize(deg+1);
      rep(i,deg){
        int nv = v[ov][i];
        if(nv == par[ov])continue;
        dp[ov][i] = dp[nv][sz(v[nv])];
        dp[ov][deg] = f(dp[ov][deg],dp[ov][i],w[ov][i]);
      }
    }
    vi ans(n,-1);
    for(int _ = n-1;_ >= 0;_--){
      int ov = ord[_];
      if(ov == -1)continue;
      int deg = sz(v[ov]);
      vi L(deg+1),R(deg+1);
      rep(i,deg)L[i+1] = f(L[i],dp[ov][i],w[ov][i]);
      for(int i = deg-1;i >= 0;i--)R[i] = f(R[i+1],dp[ov][i],w[ov][i]);
      ans[ov] = L[deg];
      rep(i,deg){
        int nv = v[ov][i];
        if(nv == par[ov])continue;
        dp[nv][p_idx[nv]] = g(L[i],R[i+1]);
      }
    }
    res = res-*max_element(ALL(ans));
    cout << res << "\n";
  }
  

  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3556
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct Edge{
    int idx, val;
    Edge(int idx, int val) : idx(idx), val(val) {}
};

constexpr long long INF = 1e18;

int main() {
    while(true) {
        int N;
        cin >> N;
        if(N == 0) return 0;
        vector<vector<pair<int, Edge>>> G(N);
        vector<int> P(N), D(N);
        long long edge_sum = 0;
        for(int i = 1; i < N; i++) {
            cin >> P[i];
            P[i]--;
        }
        for(int i = 1; i < N; i++) {
            cin >> D[i];
            edge_sum += D[i];
            G[i].push_back({P[i], Edge(i, D[i])});
            G[P[i]].push_back({i, Edge(i, D[i])});
        }

        long long delete_sum = 0;
        set<int> delete_edge;
        for(int i = 0; i < N; i++) {
            if(G[i].size() != 1) continue;
            delete_edge.insert(G[i][0].second.idx);
            delete_sum += G[i][0].second.val;
        }
        
        int s = 0;
        while(G[s].size() == 1) s++;

        vector<long long> dist(N, INF);
        dist[s] = 0;
        priority_queue<pair<long long, int>> pq;
        pq.push({0, s});
        while(pq.size()) {
            auto [d, v] = pq.top(); pq.pop();
            for(auto [nv, e] : G[v]) {
                if(delete_edge.count(e.idx)) continue;
                if(dist[nv] <= dist[v] + e.val) continue;
                dist[nv] = dist[v] + e.val;
                pq.push({-dist[nv], nv});
            }
        }

        long long ma = 0;
        for(int i = 0; i < N; i++) {
            if(dist[i] == INF) continue;
            if(ma < dist[i]) {
                ma = dist[i];
                s = i;
            }
        }

        dist = vector<long long>(N, INF);
        dist[s] = 0;
        pq.push({0, s});
        while(pq.size()) {
            auto [d, v] = pq.top(); pq.pop();
            for(auto [nv, e] : G[v]) {
                if(delete_edge.count(e.idx)) continue;
                if(dist[nv] <= dist[v] + e.val) continue;
                dist[nv] = dist[v] + e.val;
                pq.push({-dist[nv], nv});
            }
        }

        ma = 0;
        for(int i = 0; i < N; i++) {
            if(dist[i] == INF) continue;
            if(ma < dist[i]) {
                ma = dist[i];
                s = i;
            }
        }

        long long ans = edge_sum + (edge_sum - delete_sum) * 2 - ma;
        cout << ans << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3488
final_rank: 2

code_snippet: // #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#ifdef DEBUG
#include "cpp-dump/dump.hpp"
#define dump(...) cpp_dump(__VA_ARGS__)
#else
#define dump(...)
#endif
using namespace std;
#define rep(i,n) for (long long i=0;i<n;i++)
#define loop(i,m,n) for(long long i=m;i<=n;i++)
#define range(value,range) for(const auto &value : range)
#define ll long long
#define vl vector<long long>
#define vvl vector<vector<long long>>
#define vdbg(a) rep(ii,a.size()){cout<<a[ii]<<" ";}cout<<endl;
#define vvdbg(a) rep(ii,a.size()){rep(jj,a[ii].size()){cout<<a[ii][jj]<<" ";}cout<<endl;}
#define inf 4000000000000000000LL
#define mod 998244353
const int lim = INT16_MAX;
map<pair<int, int>,ll> memo;

template<class Monoid> struct ReRooting {
    using Graph = vector<vector<int>>;
    using MergeFunc = function<Monoid(Monoid, Monoid)>;
    using AddNodeFunc = function<Monoid(int,int, Monoid)>;
    
    // core member
    Graph G;
    Monoid IDENTITY;
    MergeFunc MERGE;
    AddNodeFunc ADDNODE;
    
    // inner data
    vector<vector<Monoid>> dp;
    
    // constructor
    ReRooting() {}
    ReRooting(const Graph &g, const Monoid &identity,
              const MergeFunc &merge, const AddNodeFunc &addnode) {
        G = g;
        IDENTITY = identity;
        MERGE = merge;
        ADDNODE = addnode;
        build();
    }
    
    // re-looting dp
    Monoid rec(int v, int p) {
        Monoid res = IDENTITY;
        dp[v].assign(G[v].size(), IDENTITY);
        for (int i = 0; i < G[v].size(); ++i) {
            int v2 = G[v][i];
            if (v2 == p) continue;
            dp[v][i] = rec(v2, v);
            res = MERGE(res, dp[v][i]);
        }
        return ADDNODE(v,p, res);
    }
    void rerec(int v, int p, Monoid pval) {
        for (int i = 0; i < G[v].size(); ++i) {
            int v2 = G[v][i];
            if (v2 == p) {
                dp[v][i] = pval;
                continue;
            }
        }
        vector<Monoid> left(G[v].size() + 1, IDENTITY);
        vector<Monoid> right(G[v].size() + 1, IDENTITY);
        for (int i = 0; i < G[v].size(); ++i) {
            left[i + 1] = MERGE(left[i], dp[v][i]);
            right[i + 1] = MERGE(right[i], dp[v][(int)G[v].size() - i - 1]);
        }
        for (int i = 0; i < G[v].size(); ++i) {
            int v2 = G[v][i];
            if (v2 == p) continue;
            Monoid pval2 = MERGE(left[i], right[(int)G[v].size() - i - 1]);
            rerec(v2, v, ADDNODE(v,v2, pval2));
        }
    }
    void build() {
        dp.assign(G.size(), vector<Monoid>());
        int root = 0, nullparent = -1;
        rec(root, nullparent);
        rerec(root, nullparent, IDENTITY);
    }
    
    // getter
    Monoid get(int v) {
        Monoid res = IDENTITY;
        for (int i = 0; i < G[v].size(); ++i) {
            res = MERGE(res, dp[v][i]);
        }
        return ADDNODE(v,lim, res);
    }
    
    // dump
    friend constexpr ostream& operator << (ostream &os, const ReRooting<Monoid> &rr) {
        for (int v = 0; v < rr.G.size(); ++v) {
            for (int i = 0; i < rr.G[v].size(); ++i) {
                os << v << " -> " << rr.G[v][i] << ": " << rr.dp[v][i] << endl;
            }
        }
        return os;
    }
};

ll solve() {
    
    ll n;
    cin >> n;
    memo.clear();
    if (n == 0) return 1;
    vector<vector<int>> G(n);
    vector<ll> P(n), D(n);
    for (ll i = 0; i < n-1; ++i) {
        int p;
        cin >> p;
        --p;
        G[i+1].push_back(p);
        G[p].push_back(i+1);
        P[i] = p;
    }
    for (ll i = 0; i < n-1; ++i) {
        ll d;
        cin >> d;
        memo[{(int)i+1,P[i]}] = d;
        memo[{P[i],(int)i+1}] = d;
    }

    dump(memo);
    dump(G | cpp_dump::index());

    // 行って戻るコスト: 部分木の中のパスグラフの最大コスト
    using Monoid = pair<ll, ll>;
    Monoid identity = {0,0};
    auto merge = [&](Monoid a, Monoid b) -> Monoid{
        ll fir = a.first+b.first;
        ll sec = max(a.second, b.second);

        return {fir,sec};
    };

    auto addnode = [&](int from, int to, Monoid a) -> Monoid {
        if (to == lim) {
            return a;
        }

        if (a.first == 0) {
            return {memo[{from,to}],0};
        }

        return {memo[{from,to}]*3+a.first, memo[{from,to}]+a.second};
    };

    ReRooting<Monoid> reroot(G, identity,merge,addnode);

    ll ans = inf;
    for (ll i = 0; i < n; ++i) {
        ans = min(ans,reroot.get(i).first - reroot.get(i).second);
    }

    cout << ans << endl;

    return 0;

}

int main(){
    while(1){
        if(solve()==1)break;
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4004
final_rank: 17

code_snippet: // #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#ifdef DEBUG
#include "cpp-dump/dump.hpp"
#define dump(...) cpp_dump(__VA_ARGS__)
#else
#define dump(...)
#endif
using namespace std;
#define rep(i,n) for (long long i=0;i<n;i++)
#define loop(i,m,n) for(long long i=m;i<=n;i++)
#define range(value,range) for(const auto &value : range)
#define ll long long
#define vl vector<long long>
#define vvl vector<vector<long long>>
#define vdbg(a) rep(ii,a.size()){cout<<a[ii]<<" ";}cout<<endl;
#define vvdbg(a) rep(ii,a.size()){rep(jj,a[ii].size()){cout<<a[ii][jj]<<" ";}cout<<endl;}
#define inf 4000000000000000000LL
#define mod 998244353
const int lim = INT16_MAX;
map<pair<int, int>,ll> memo;

template<class Monoid> struct ReRooting {
    using Graph = vector<vector<int>>;
    using MergeFunc = function<Monoid(Monoid, Monoid)>;
    using AddNodeFunc = function<Monoid(int,int, Monoid)>;
    
    // core member
    Graph G;
    Monoid IDENTITY;
    MergeFunc MERGE;
    AddNodeFunc ADDNODE;
    
    // inner data
    vector<vector<Monoid>> dp;
    
    // constructor
    ReRooting() {}
    ReRooting(const Graph &g, const Monoid &identity,
              const MergeFunc &merge, const AddNodeFunc &addnode) {
        G = g;
        IDENTITY = identity;
        MERGE = merge;
        ADDNODE = addnode;
        build();
    }
    
    // re-looting dp
    Monoid rec(int v, int p) {
        Monoid res = IDENTITY;
        dp[v].assign(G[v].size(), IDENTITY);
        for (int i = 0; i < G[v].size(); ++i) {
            int v2 = G[v][i];
            if (v2 == p) continue;
            dp[v][i] = rec(v2, v);
            res = MERGE(res, dp[v][i]);
        }
        return ADDNODE(v,p, res);
    }
    void rerec(int v, int p, Monoid pval) {
        for (int i = 0; i < G[v].size(); ++i) {
            int v2 = G[v][i];
            if (v2 == p) {
                dp[v][i] = pval;
                continue;
            }
        }
        vector<Monoid> left(G[v].size() + 1, IDENTITY);
        vector<Monoid> right(G[v].size() + 1, IDENTITY);
        for (int i = 0; i < G[v].size(); ++i) {
            left[i + 1] = MERGE(left[i], dp[v][i]);
            right[i + 1] = MERGE(right[i], dp[v][(int)G[v].size() - i - 1]);
        }
        for (int i = 0; i < G[v].size(); ++i) {
            int v2 = G[v][i];
            if (v2 == p) continue;
            Monoid pval2 = MERGE(left[i], right[(int)G[v].size() - i - 1]);
            rerec(v2, v, ADDNODE(v,v2, pval2));
        }
    }
    void build() {
        dp.assign(G.size(), vector<Monoid>());
        int root = 0, nullparent = -1;
        rec(root, nullparent);
        rerec(root, nullparent, IDENTITY);
    }
    
    // getter
    Monoid get(int v) {
        Monoid res = IDENTITY;
        for (int i = 0; i < G[v].size(); ++i) {
            res = MERGE(res, dp[v][i]);
        }
        return ADDNODE(v,lim, res);
    }
    
    // dump
    friend constexpr ostream& operator << (ostream &os, const ReRooting<Monoid> &rr) {
        for (int v = 0; v < rr.G.size(); ++v) {
            for (int i = 0; i < rr.G[v].size(); ++i) {
                os << v << " -> " << rr.G[v][i] << ": " << rr.dp[v][i] << endl;
            }
        }
        return os;
    }
};

ll solve() {
    
    ll n;
    cin >> n;
    memo.clear();
    if (n == 0) return 1;
    vector<vector<int>> G(n);
    vector<ll> P(n), D(n);
    for (ll i = 0; i < n-1; ++i) {
        int p;
        cin >> p;
        --p;
        G[i+1].push_back(p);
        G[p].push_back(i+1);
        P[i] = p;
    }
    for (ll i = 0; i < n-1; ++i) {
        ll d;
        cin >> d;
        memo[{(int)i+1,P[i]}] = d;
        memo[{P[i],(int)i+1}] = d;
    }

    dump(memo);
    dump(G | cpp_dump::index());

    // 行って戻るコスト: 部分木の中のパスグラフの最大コスト
    using Monoid = pair<ll, ll>;
    Monoid identity = {0,0};
    auto merge = [&](Monoid a, Monoid b) -> Monoid{
        ll fir = a.first+b.first;
        ll sec = max(a.second, b.second);

        return {fir,sec};
    };

    auto addnode = [&](int from, int to, Monoid a) -> Monoid {
        if (to == lim) {
            return a;
        }

        if (a.first == 0) {
            return {memo[{from,to}],0};
        }

        return {memo[{from,to}]*3+a.first, memo[{from,to}]+a.second};
    };

    ReRooting<Monoid> reroot(G, identity,merge,addnode);

    ll ans = inf;
    for (ll i = 0; i < n; ++i) {
        ans = min(ans,reroot.get(i).first - reroot.get(i).second);
    }

    cout << ans << endl;

    return 0;

}

int main(){
    while(1){
        if(solve()==1)break;
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4008
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i,n) for(int i = 0;i < n;i++)

#define int ll

pair<int,int> far(int s, int n, const vector<vector<pair<int,int>>> &adj)
{
    vector<int> dist(n, (1LL<<60));
    priority_queue<pair<int,int>> que;
    que.emplace(0,s);
    dist.at(s) = 0;

    while(!que.empty())
    {
        int d = - que.top().first;
        int now = que.top().second;
        que.pop();
        if(dist.at(now) < d) continue;
        dist.at(now) = d;
        for(auto [nxt, c] : adj.at(now))
        {
            if(dist.at(nxt) < d + c) continue;
            que.emplace(-(d+c), nxt);
        }
    }
    int pnt = s;
    int d = 0;
    rep(i,n)
    {
        if(dist.at(i) > d)
        {
            d = dist.at(i);
            pnt = i;
        }
    }
    return make_pair(pnt, d);
}

void main_()
{
    int n;
    cin >> n;
    if(!n) exit(0);

    vector<int> b(n-1), c(n-1);
    rep(i,n-1) cin >> b[i];
    rep(i,n-1) b[i]--;
    rep(i,n-1) cin >> c[i];

    int sum_a = 0;
    rep(i,n-1) sum_a += c[i];

    vector<int> deg(n,1);
    deg[0] = 0;
    rep(i,n-1) deg.at(b[i]) += 1;

    set<int> st;
    rep(i,n)
        if(deg.at(i) >= 2) st.insert(i);

   int m = st.size();
   map<int, int> mp;
   int idx = 0;
   for(int i : st) mp[i] = idx++;
   // 1 ~ m
   vector<vector<pair<int,int>>> adj(m);
   int sum_b = 0;
   rep(i,n-1)
   {
       // i + 1 to b[i]
       int from = i + 1;
       if(st.find(from) == st.end()) continue;
       if(st.find(b[i]) == st.end()) continue;

       adj.at(mp[from]).emplace_back(mp[b[i]], c[i]);
       adj.at(mp[b[i]]).emplace_back(mp[from], c[i]);
       sum_b += c[i];
   }
   pair<int,int> one = far(0, m, adj);
   pair<int,int> two = far(one.first, m, adj);
   int dist = two.second;

   int ans = sum_a + (2*sum_b) - dist;
   cout << ans << endl;
}


signed main()
{
    while(1) main_();
}
accuracy: 1
time_ms: 20
memory_kb: 3624
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(int i = a; i < n; i++)
#define rrep(i, a, n) for(int i = a; i >= n; i--)
#define inr(l, x, r) (l <= x && x < r)
#define ll long long
#define ld long double

constexpr int IINF = 1001001001;
constexpr ll INF = 9e18;

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

int main() {
    while(1){
        int n; cin >> n;
        if(n == 0) break;
        vector<vector<pair<int,int>>> g(n);
        vector<int> p(n-1), d(n-1);
        int dsum = 0;
        rep(i,0,n-1){
            cin >> p[i];
            p[i]--;
        }
        rep(i,0,n-1){
            cin >> d[i];
            dsum += d[i]*3;
        }
        rep(i,0,n-1){
            g[i+1].push_back({p[i],d[i]});
            g[p[i]].push_back({i+1,d[i]});
        }
        int ans = IINF;
        int maxdist;
        int res;

        auto dfs = [&](auto dfs, int v, int p, int dist)->void{
            if(g[v].size() >= 2 || g[v][0].first != p){
                chmax(maxdist, dist);
            }else{
                res -= 2*g[v][0].second;
            }
            for(auto nv: g[v]){
                if(nv.first == p) continue;
                dfs(dfs, nv.first, v, dist+nv.second);
            }
        };
        
        auto solve = [&](int i)->int{
            maxdist = 0;
            res = dsum;
            dfs(dfs, i, -1, 0);
            res -= maxdist;
            return res;
        };

        rep(i,0,n){
            chmin(ans,solve(i));
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 3504
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll LINF = 1e18;

int main(){
    while(1){
        int N; cin >> N;
        if(N == 0) break;
        vector<int> P(N - 1); for(int i = 0; i < N - 1; i++) cin >> P[i];
        vector<int> D(N - 1); for(int i = 0; i < N - 1; i++) cin >> D[i];

        vector<vector<pair<int, int>>> G(N);
        for(int i = 0; i < N - 1; i++){
            int u = P[i] - 1, v = i + 1;
            G[u].emplace_back(make_pair(v, D[i]));
            G[v].emplace_back(make_pair(u, D[i]));
        }

        auto dfs = [&](auto f, int u, int par) -> ll {
            ll res = 0;
            for(auto [v, d] : G[u]){
				if(v == par) continue;
                if(G[v].size() == 1) continue;
                else{
                    res = max(res, f(f, v, u) + d);
                }
            }
            return res;
        };

        // auto rec = [&](auto f, int u, int par) -> ll {
        //     ll res = 0;
        //     for(auto [v, d] : G[u]){
		// 		cout << "(" << v << "," << d << ")";
        //         if(v == par) continue;
        //         if(G[v].size() == 1) res += d;
        //         else{
        //             f(f, v, u);
        //             res += d * 3;
        //         }
        //     }
        //     return res;
        // };

        ll ans = LINF;
		ll num = 0;
		for(int i = 0; i < N; i++){
			for(auto [j, d] : G[i]){
				if(i > j) continue;
				if(G[i].size() == 1 || G[j].size() == 1){
					num += d;
				}
				else num += d * 3;
			}
		}
        for(int i = 0; i < N; i++){
            if(G[i].size() == 1) continue;
			ll val = dfs(dfs, i, -1);
			// cout << num << " " << val << " ";
            ans = min(ans, num - val);
        }
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3484
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i,n) for(int i=0;i<n;i++)

using Edge=pair<int,int>;
using Graph=vector<vector<Edge>>;


#define INF 1<<30

void dijkstra(Graph& g, int s, int n, vector<int>& dist){
  dist.assign(n, INF);
  dist[s]=0;

  vector<int> seen(n,false);

  for(;;){
    int pos=-1;
    int mi=INF;
    rep(i,n){
      if(seen[i] || mi<= dist[i]) continue;
      pos=i;
      mi=dist[i];
    }
    if(pos==-1) break;

    seen[pos]=true;
    rep(i,g[pos].size()){
      int next=g[pos][i].first;
      int cost=g[pos][i].second;
      dist[next]=min(dist[next], dist[pos]+cost);
    }
  }
}

int solve(int n){
  vector<int> p(n-1), d(n-1);
  rep(i,n-1){cin>>p[i];p[i]--;}
  rep(i,n-1) cin>>d[i];

  int res=0;
  rep(i,n-1) res+=d[i];
  res*=3;

  Graph graph(n);
  rep(i,n-1){
    graph[i+1].push_back({p[i], d[i]});
    graph[p[i]].push_back({i+1, d[i]});
  }

  rep(i,n){
    if(graph[i].size()==1){
      res-=2*graph[i][0].second;
      int to=graph[i][0].first;
      graph[i][0].second=0;
      rep(j,graph[to].size()) if(graph[to][j].first==i) graph[to][j].second=0;
    }
  }

  vector<int> dist;
  dijkstra(graph,0,n,dist);
  int tmp=0;
  rep(i,n) if(dist[tmp]<dist[i]) tmp=i;
  dijkstra(graph,tmp,n,dist);
  tmp=0;
  rep(i,n) if(dist[tmp]<dist[i]) tmp=i;
  res-=dist[tmp];
  return res;

}

int main(){
  for(;;){
    int n; cin>>n;
    if(n==0) return 0;
    cout<<solve(n)<<endl;
  }
}
accuracy: 1
time_ms: 80
memory_kb: 3504
final_rank: 6

code_snippet: #include <bits/stdc++.h>

bool solve() {
    int N;
    std::cin >> N;
    if (N == 0) return false;
    std::vector<std::vector<int>> g(N);
    for (int i{1} ; i < N ; i++) {
        int P;
        std::cin >> P;
        P--;
        g[P].push_back(i);
        g[i].push_back(P);
    }
    std::vector<int> D(N);
    for (int i{1} ; i < N ; i++) {
        std::cin >> D[i];
    }
    if (N == 2) {
        std::cout << D[1] << '\n';
        return true;
    }
    auto cost{[&](int u, int v) -> int {
        assert(0 <= u and u < N);
        assert(0 <= v and v < N);
        return D[std::max(u, v)];
    }};
    std::vector<bool> leaf(N);
    for (int i{} ; i < N ; i++) {
        leaf[i] = (g[i].size() == 1u);
    }
    std::map<std::pair<int, int>, long long> dp1;
    // return to v
    auto rec1{[&](auto rec, int v, int p) -> long long {
        if (dp1.find(std::pair{ p, v }) != dp1.end()) {
            return dp1[std::pair{ p, v }];
        }
        long long res{};
        for (auto x : g[v]) {
            if (x == p) continue;
            if (leaf[x]) res += cost(v, x);
            else res += 3 * cost(v, x) + rec(rec, x, v);
        }
        return dp1[std::pair{ p, v }] = res;
    }};
    std::map<std::pair<int, int>, long long> dp2;
    auto rec2{[&](auto rec, int v, int p) -> long long {
        if (dp2.find(std::pair{ p, v }) != dp2.end()) {
            return dp2[std::pair{ p, v }];
        }
        long long base{};
        for (auto x : g[v]) {
            if (x == p) continue;
            if (leaf[x]) base += cost(v, x);
            else base += 3 * cost(v, x) + rec1(rec1, x, v);
        }
        long long res{base};
        for (auto x : g[v]) {
            if (x == p) continue;
            if (leaf[x]) continue;
            long long value{base};
            value -= 3 * cost(v, x) + rec1(rec1, x, v);
            value += 2 * cost(v, x) + rec(rec, x, v);
            res = std::min(res, value);
        }
        return dp2[std::pair{ p, v }] = res;
    }};
    long long ans{(long long)9e18};
    for (int s{} ; s < N ; s++) {
        if (leaf[s]) continue;
        ans = std::min(ans, rec2(rec2, s, -1));
    }
    std::cout << ans << '\n';
    return true;
}

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    while (solve()) ;
}
accuracy: 1
time_ms: 170
memory_kb: 3996
final_rank: 19