树形dp
题号:Codeforces 461B
题意:
输入 n ,表示有一个 n 个节点的树;
输入 n-1 个数 P[0] ~ P[n-1],p[i]表示无向边将 i+1 和 P[i] 连接起来
输入 n 个数 ,表示每个节点的颜色,0为白色,1为黑色
要切断 k 条边变成 k 个连通分量,每个分量有且只有一个方案数,求有多少种分割方案;
思路:
从根节点向下递归,上层利用回溯计算结果;
实在搞不懂,先记录一下
撸代码:
1#include<stdio.h>
2#include<string.h>
3#define N 101000
4struct Edge
5{
6 int to,nex;
7} edge[N*3];
8int cnt,n;
9int head[N];/**链表头结点*/
10int c[N];/**标记节点黑白*/
11long long dp[N][2];
12void init()
13{
14 memset(head,-1,sizeof(head));
15 cnt=0;
16}
17
18void addEdge(int u,int v)
19{
20 edge[cnt].to=v;
21 edge[cnt].nex=head[u];
22 head[u]=cnt++;
23
24 edge[cnt].to=u;
25 edge[cnt].nex=head[v];
26 head[v]=cnt++;
27
28}
29long long mod=1000000007;
30void dfs(int u,int fa)
31{
32
33 dp[u][c[u]]=1;
34 for(int i=head[u]; i!=-1; i=edge[i].nex)
35 {
36 int v=edge[i].to;
37 if(v==fa)
38 continue;
39 dfs(v,u);/**从上往下遍历 ,利用回溯*/
40
41 /**dp 数组含义:以U为根,当前连通块有黑点 [1] 或没有黑点 [0] 方案数*/
42
43 /**子树和根都有黑点,则边剪掉;根为黑点但子树无黑点,保留边;根无黑点而子树有黑点*/
44 dp[u][1]=(dp[u][1]*dp[v][1]%mod+dp[u][0]*dp[v][1]%mod+dp[u][1]*dp[v][0]%mod)%mod;
45
46 /**没有黑点就要保留所有*/
47 dp[u][0]=(dp[u][0]*dp[v][0]%mod+dp[u][0]*dp[v][1]%mod)%mod;
48 }
49
50}
51
52int main()
53{
54
55 scanf("%d",&n);
56 init();
57 int v;
58 for(int i=1; i<n; i++)
59 {
60 scanf("%d",&v);
61 addEdge(v,i);
62 }
63
64 for(int i=0; i<n; i++)
65 {
66 scanf("%d",&c[i]);
67 }
68 dfs(0,0);
69 printf("begin:
");
70 for(int i=0;i<n;i++)
71 {
72 printf("i=%d : %lld %lld
",i,dp[i][0],dp[i][1]);
73 }
74 printf("%lld
",dp[0][1]);
75 return 0;
76}