CF 461B Appleman and Tree 树形DP

Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other vertices are colored white.

Consider a set consisting of k (0 ≤ k < n) edges of Appleman's tree. If Appleman deletes these edges from the tree, then it will split into (k + 1) parts. Note, that each part will be a tree with colored vertices.

Now Appleman wonders, what is the number of sets splitting the tree in such a way that each resulting part will have exactly one black vertex? Find this number modulo 1000000007 (109 + 7).

Input

The first line contains an integer n (2  ≤ n ≤ 105) — the number of tree vertices.

The second line contains the description of the tree: n - 1 integers p0, p1, ..., pn - 2 (0 ≤ pi ≤ i). Where pi means that there is an edge connecting vertex (i + 1) of the tree and vertex pi. Consider tree vertices are numbered from 0 to n - 1.

The third line contains the description of the colors of the vertices: n integers x0, x1, ..., xn - 1 (xi is either 0 or 1). If xi is equal to 1, vertex i is colored black. Otherwise, vertex i is colored white.

Output

Output a single integer — the number of ways to split the tree modulo 1000000007 (109 + 7).

Sample test(s)
input
3
0 0
0 1 1
output
2
input
6
0 1 1 0 4
1 1 0 0 1 0
output
1
input
10
0 1 2 1 4 4 4 0 8
0 0 0 1 0 1 1 0 0 1
output
27





题意:
一棵树,n个节点,编号为0~n-1
每一个节点涂有黑色或者白色,1代表黑色,0代表白色
若在树上去掉k条边,就把树分成k+1部分,每一个部分也是一棵树,若每一部分都有且只有一个节点是黑色,
则这是一个合理的操作。
求合理操作的方案数%(1e9+7)

如果把黑色看成节点的值为1,白色看成节点的值为0
一棵树的值=树上所有节点的值之和
则这道题转化为:
把一棵树分成若干个部分,每一部分的值都为1的方案数。

树形DP

dp[i][0] : 以i为根的子树,i所在部分的值为0的方案数%mod
dp[i][1] : 以i为根的子树,i所在部分的值为1的方案数%mod

以root=0进行DFS
则输出:dp[0][1]


代码:



 1 #include<cstdio>
 2 #include<cstring>
 3 
 4 using namespace std;
 5 
 6 const int maxn=1e5+5;
 7 const int mod=1e9+7;
 8 #define ll long long
 9 
10 struct Edge
11 {
12     int to,next;
13 };
14 Edge edge[maxn<<1];
15 int head[maxn];
16 int tot=0;
17 ll dp[maxn][2];
18 int cost[maxn];
19 
20 void init()
21 {
22     memset(head,-1,sizeof head);
23     memset(dp,0,sizeof dp);
24 }
25 
26 void addedge(int u,int v)
27 {
28     edge[tot].to=v;
29     edge[tot].next=head[u];
30     head[u]=tot++;
31 }
32 
33 void solve(int );
34 void dfs(int ,int );
35 
36 int main()
37 {
38     init();
39     int n;
40     scanf("%d",&n);
41     for(int i=1;i<n;i++)
42     {
43         int p;
44         scanf("%d",&p);
45         addedge(i,p);
46         addedge(p,i);
47     }
48     for(int i=0;i<n;i++)
49     {
50         scanf("%d",&cost[i]);
51     }
52     solve(n);
53     return 0;
54 }
55 
56 void solve(int n)
57 {
58     dfs(0,-1);
59     printf("%d
",(int)dp[0][1]);
60     return ;
61 }
62 
63 void dfs(int u,int pre)
64 {
65     if(cost[u])
66     {
67         dp[u][1]=1;
68         dp[u][0]=0;
69     }
70     else
71     {
72         dp[u][0]=1;
73         dp[u][1]=0;
74     }
75     for(int i=head[u];~i;i=edge[i].next)
76     {
77         int v=edge[i].to;
78         if(v==pre)
79             continue;
80         dfs(v,u);
81         if(cost[u])
82         {
83             dp[u][1]*=(dp[v][0]+dp[v][1]);
84             dp[u][1]%=mod;
85         }
86         else
87         {
88             dp[u][1]=dp[u][1]*(dp[v][0]+dp[v][1])+dp[u][0]*dp[v][1];
89             dp[u][1]%=mod;
90             dp[u][0]*=(dp[v][0]+dp[v][1]);
91             dp[u][0]%=mod;
92         }
93     }
94 }
View Code
























原文地址:https://www.cnblogs.com/-maybe/p/4767145.html