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 ",d[0][1]); 59 return 0; 60 }