Description
给出一个以
1
为根的
count = 0 // global integer variable
rnd() { // this function is used in paint code
return 0 or 1 equiprobably
}
paint(s) {
if (count is even) then paint s with white color
else paint s with black color
count = count + 1
if rnd() = 1 then children = [array of vertex s children in ascending order of their numbers]
else children = [array of vertex s children in descending order of their numbers]
for child in children { // iterating over children array
if rnd() = 1 then paint(child) // calling paint recursively
}
}
Input
第一行输入一整数
n
表示节点数,之后
Output
输出不同的染色方案数,结果模 109+7
Sample Input
4
1 2 1
Sample Output
8
Solution
设
dp[u][0]
和
dp[i][1]
分别为染以
u
节点为根的子树偶数个点和奇数个点的方案数,对于节点
假设经过
u
节点染了奇数个点,则除
假设经过
注意到
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100005;
#define mod 1000000007
void add(int &x,int y)
{
x=x+y>=mod?x+y-mod:x+y;
}
int n,dp[maxn][2];
vector<int>g[maxn];
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
int p;
scanf("%d",&p);
g[p].push_back(i);
}
for(int u=n;u>=1;u--)
{
dp[u][1]=1,dp[u][0]=0;
if(!g[u].size())continue;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
int t0=dp[u][0],t1=dp[u][1];
add(dp[u][1],(ll)t1*dp[v][0]%mod);
add(dp[u][1],(ll)t0*dp[v][1]%mod);
add(dp[u][0],(ll)t0*dp[v][0]%mod);
add(dp[u][0],(ll)t1*dp[v][1]%mod);
}
add(dp[u][0],dp[u][0]);
add(dp[u][1],dp[u][1]);
int a=1,b=1,c=0;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
add(a,(ll)a*dp[v][0]%mod);
int tb=b,tc=c;
add(b,(ll)tc*dp[v][1]%mod);
add(c,(ll)tb*dp[v][1]%mod);
}
add(dp[u][0],mod-c);
add(dp[u][1],mod-a);
}
printf("%d\n",(dp[1][1]+dp[1][0])%mod);
return 0;
}