51 Nod 1500 苹果曼和树(树形dp)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1500

 

思路:

树形dp。

我们考虑当前结点 i ,对于结点 i ,它可以属于它的子树,也可以不属于,换句话说,我们可以计算出与 i 结点相连的连通块中是否具有黑点的方案数。

于是,d【i】【1】表示包含 i 的连通块中含有黑点,d【i】【0】表示不含有。

接下来考虑状态转移方程:

  d[u][1]=(d[u][1]*(d[v][0]+d[v][1])+d[u][0]*d[v][1])%mod;
  d[u][0]=(d[u][0]*(d[v][1]+d[v][0]))%mod;

上面的只是我个人认为的。。。可能是错的哈~

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<sstream>
 6 #include<vector>
 7 #include<stack>
 8 #include<queue>
 9 #include<cmath>
10 #include<map>
11 #include<set>
12 using namespace std;
13 typedef long long ll;
14 typedef pair<int,int> pll;
15 const int INF = 0x3f3f3f3f;
16 const int maxn = 1e5+5;
17 const int mod = 1000000007;
18 
19 int val[maxn];
20 ll d[maxn][2];
21 
22 vector<int> g[maxn];
23 
24 void dfs(int u, int fa)
25 {
26     if(val[u])  d[u][1]=1;
27     else d[u][0]=1;
28     for(int i=0;i<g[u].size();i++)
29     {
30         int v=g[u][i];
31         if(v==fa)  continue;
32         dfs(v,u);
33         d[u][1]=(d[u][1]*(d[v][0]+d[v][1])+d[u][0]*d[v][1])%mod;
34         d[u][0]=(d[u][0]*(d[v][1]+d[v][0]))%mod;
35     }
36 }
37 
38 int main()
39 {
40     //freopen("in.txt","r",stdin);
41     int n;
42     scanf("%d",&n);
43     for(int i=1;i<n;i++)
44     {
45         int x;
46         scanf("%d",&x);
47         g[x].push_back(i);
48         g[i].push_back(x);
49     }
50 
51     memset(d,0,sizeof(d));
52 
53     for(int i=0;i<n;i++)
54     {
55         scanf("%d",&val[i]);
56     }
57     dfs(0,-1);
58     printf("%lld\n",d[0][1]);
59     return 0;
60 }

 

posted @ 2017-06-27 20:58  Kayden_Cheung  阅读(239)  评论(0编辑  收藏  举报
//目录