[CF461B] Appleman and Tree
[CF461B] Appleman and Tree
Description
给你一棵有 \(n\) 个节点的树,下标从 \(0\) 开始。
第 \(i\) 个节点可以为白色或黑色。
现在你可以从中删去若干条边,使得剩下的每个部分恰有一个黑色节点。
问有多少种符合条件的删边方法,答案对 \(10^9+7\) 取模。
Solution
-
这题考虑断开哪些边反而不好计算,转而考虑进行树形DP。
-
考虑设 \(f_{i,j}\) 表示以 \(i\) 为根的联通块内有 \(j\) 个黑点的方案数,显然 \(j=0\) 或 \(j=1\)。
我们考虑从子树往下转移时,父子节点的边是否断开即可转移。
设 \(fa_y=x\)。
则有若该条边断开,那么 \(y\) 子树必须合法,即有 \(f_{x,0}\leftarrow f_{x,0}\times f_{y,1}\) 和 \(f_{x,1}\leftarrow f_{x,1}\times f_{y,1}\)。
若连上则有 \(y\) 合法性可以转移给 \(x\),即有 \(f_{x,0}\leftarrow f_{x,0}\times f_{y,0}\) 和 \(f_{x,1}\leftarrow f_{x,0}\times f_{y,1}+f_{x,1}\times f_{y,0}\)。
-
答案为 \(f_{0,1}\)。记得读入点颜色时是 \(0\to n-1\)。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+7;
vector<int> G[N<<2];
int n,col[N];
const int mod=1e9+7;
int dp[N][10];
void dfs(int u,int father){
dp[u][col[u]]=1;
for(int k:G[u]){
if(k==father) continue;
dfs(k,u);
dp[u][1]=dp[u][1]%mod*(dp[k][0]%mod+dp[k][1]%mod)%mod+dp[u][0]%mod*dp[k][1]%mod;
dp[u][1]%=mod;
dp[u][0]=dp[u][0]%mod*(dp[k][0]%mod+dp[k][1]%mod)%mod;
dp[u][0]%=mod;
}
}
signed main(){
cin>>n;
for(int i=1;i<=n-1;i++){
int p;scanf("%lld",&p);
G[p].push_back(i);
G[i].push_back(p);
}
for(int i=0;i<n;i++){
scanf("%lld",&col[i]);
}
dfs(0,-1);
printf("%lld",dp[0][1]%mod);
}