g(node, i, なし) は
g(node, i-1, なし) × --- g(i番目の子, all, なし) ... OK
+ g(node, i-1, なし) × -|- g(i番目の子, all, なし) ... だめ(i番目の子以下が黒なしで確定しちゃう
+ g(node, i-1, なし) × --- g(i番目の子, all, あり) ... だめ
+ g(node, i-1, なし) × -|- g(i番目の子, all, あり) ... OK
+ g(node, i-1, あり) × --- g(i番目の子, all, なし) ... だめ
+ g(node, i-1, あり) × -|- g(i番目の子, all, なし) ... だめ(i番目の子以下が黒なしで確定しちゃう
+ g(node, i-1, あり) × --- g(i番目の子, all, あり) ... だめ
+ g(node, i-1, あり) × -|- g(i番目の子, all, あり) ... だめ
g(node, i, あり) は
g(node, i-1, なし) × --- g(i番目の子, all, なし) ... だめ
+ g(node, i-1, なし) × -|- g(i番目の子, all, なし) ... だめ
+ g(node, i-1, なし) × --- g(i番目の子, all, あり) ... OK
+ g(node, i-1, なし) × -|- g(i番目の子, all, あり) ... だめ
+ g(node, i-1, あり) × --- g(i番目の子, all, なし) ... OK
+ g(node, i-1, あり) × -|- g(i番目の子, all, なし) ... だめ
+ g(node, i-1, あり) × --- g(i番目の子, all, あり) ... だめ
+ g(node, i-1, あり) × -|- g(i番目の子, all, あり) ... OK
- Accepted in Practice room
- 問題の条件をよりそのままコードに落とした感は出てきたが、全体的に簡潔さはあんまし変わってない気がする。。
VVI g;
VVI memo;
vector<bool> black;
ll dfs(int prev, int idx, int b) {
if(memo[b][idx]>=0) return memo[b][idx];
modll dp[2];
dp[0] = (modll)!black[idx];
dp[1] = (modll)black[idx];
REP(i, g[idx].size()) {
int ni = g[idx][i];
if(prev==ni) continue;
modll ndp[2] = {0, 0};
modll ch[2] = {dfs(idx, ni, 0), dfs(idx, ni, 1)};
REP(pi, 2) REP(ci, 2) REP(cut, 2) {
int obi = pi + (cut ? 0 : ci);
if(cut && ci==0) continue;
if(obi < 2) ndp[obi] += dp[pi] * ch[ci];
}
dp[0] = ndp[0];
dp[1] = ndp[1];
}
return memo[b][idx] = dp[b];
}
int main() {
ll N,p,v;
while(cin>>N) {
g = VVI(N);
memo = VVI(2, VI(N, -1));
black = vector<bool>(N);
REP(i, N-1) {
cin>>p;
g[i+1].PB(p);
g[p].PB(i+1);
}
REP(i, N) {
cin>>v;
black[i] = v;
}
ll ans = dfs(-1, 0, 1);
cout<<ans<<endl;
}
return 0;
}