D. Appleman and Tree
题意:给出一个树,树的顶点有颜色,要么黑的,要么白的,至少有一个黑色顶点。需要把这棵树分割成若干子树,使得每棵子树恰好有一个黑色顶点,问又多少种分割方法。
思路:树型dp,0是天然的根。。状态转移方程略神奇,是:
dp[u][1]=(dp[u][1]*dp[v][1]+dp[u][1]*dp[v][0]+dp[u][0]*dp[v][1]);
dp[u][0]=(dp[u][0]*dp[v][1]+dp[u][0]*dp[v][0]);
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define INF 10000
#define ll long long
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 100010
using namespace std;
vector<int> son[100010];
ll dp[100010][2];
int vis[100010][2];
void fun(int u){
int s=son[u].size();
for(int i=0;i<s;i++){
int v=son[u][i];
fun(v);
dp[u][1]=(dp[u][1]*dp[v][1]+dp[u][1]*dp[v][0]+dp[u][0]*dp[v][1]);
dp[u][0]=(dp[u][0]*dp[v][1]+dp[u][0]*dp[v][0]);
dp[u][1]%=1000000007;
dp[u][0]%=1000000007;
}
}
int main(){
ll n;
while(cin>>n){
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
for(int i=0;i<n-1;i++){
int u;
cin>>u;
son[u].push_back(i+1);
}
for(int i=0;i<n;i++){
bool b;
cin>>b;
if(b)
dp[i][1]=1;
else
dp[i][0]=1;
}
fun(0);
cout<<dp[0][1]<<endl;
}
return 0;
}
本文详细阐述了如何使用树形DP算法解决含有特定黑色顶点限制的树分割问题,通过状态转移方程实现了高效求解。
649

被折叠的 条评论
为什么被折叠?



