[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);
}
posted @ 2023-07-25 14:15  Zimo_666  阅读(5)  评论(0编辑  收藏  举报