codeforces Round #263(div2) D. Appleman and Tree 树形dp
题意:
给出一棵树,每个节点都被标记了黑或白色,要求把这棵树的其中k条变切换,划分成k+1棵子树,每颗子树必须有1个黑色节点,求有多少种划分方法。
题解:
树形dp
dp[x][0]表示是以x为根的树形成一块不含黑色点的方案数
dp[x][1]表示是以x为根的树形成一块含一个黑色点方案数
//зїеп:1085422276 #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <queue> #include <typeinfo> #include <map> #include <stack> typedef long long ll; #define inf 100000000 #define mod 1000000007 using namespace std; inline ll read() { ll x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } //*************************************** struct ss { int to,next; }e[200005*5]; ll dp[200005][2]; int head[200005],t,vis[200005],cl[200005]; void init(){ memset(head,0,sizeof(head)); t=1; } void add(int u,int v) { e[t].next=head[u]; e[t].to=v; head[u]=t++; } void dfs(int x,int pre) { //vis[x]=1; dp[x][cl[x]]=1; for(int i=head[x];i;i=e[i].next) { if(e[i].to==pre)continue; dfs(e[i].to,x); if(cl[x]==1){ dp[x][1]=(dp[x][1]*dp[e[i].to][0]%mod+dp[x][1]*dp[e[i].to][1])%mod; } else { dp[x][1]=(dp[x][1]*dp[e[i].to][0]%mod+dp[x][0]*dp[e[i].to][1]%mod+dp[x][1]*dp[e[i].to][1])%mod; dp[x][0]=(dp[x][0]*dp[e[i].to][1]%mod+dp[x][0]*dp[e[i].to][0])%mod; } } } int main() { init(); int n; scanf("%d",&n); int x; for(int i=0;i<n-1;i++){ scanf("%d",&x); add(i+1,x); add(x,i+1); } for(int i=0;i<n;i++) scanf("%d",&cl[i]); dfs(0,-1); cout<<dp[0][1]<<endl; return 0; }