题意:
给定一棵有 个结点的树,结点颜色为白或者黑,求删去 条边后,各联通块恰含有一个黑色结点的方案数。
链接:
https://vjudge.net/problem/CodeForces-461B
解题思路:
树形 , 表示以 为根的联通块没有黑色结点, 表示有黑色结点。对待加入的子树逐一合并,讨论连接边是否删去。
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
vector<int> G[maxn];
int a[maxn]; ll dp[maxn][2];
int n;
void dfs(int u, int f){
dp[u][0] = dp[u][1] = 0, dp[u][a[u]] = 1;
for(auto &v : G[u]){
if(v == f) continue;
dfs(v, u);
ll tp[2] = {dp[u][0], dp[u][1]};
dp[u][0] = tp[0] * dp[v][0] + tp[0] * dp[v][1], dp[u][0] %= mod;
dp[u][1] = tp[0] * dp[v][1] + tp[1] * dp[v][0] + tp[1] * dp[v][1], dp[u][1] %= mod;
}
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
cin >> n;
for(int i = 2; i <= n; ++i){
int u; cin >> u; ++u;
G[i].pb(u), G[u].pb(i);
}
for(int i = 1; i <= n; ++i) cin >> a[i];
dfs(1, 0);
cout << dp[1][1] << endl;
return 0;
}