http://codeforces.com/contest/482
其实我们只需要考虑三种情况一种从左到右成立,一种从右到左成立,一种两边都成立,答案就是前两种相加减去后一种,前两种好球,后一种用dp[i][j][k]便是第i个儿子前面的取得点的个数%2后的值,后面是这个点后面的所有取得点%2后的值,然后就写完了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn=100005;
const int mod=1000000007;
int dp[maxn][2];
vector<int>g[maxn];
int dp1[maxn][2][2];
int dp2[maxn][2];
void chan(int &p){
if(p>=mod)p=p-mod;
}
void dfs(int u){
for(int v:g[u]){
dfs(v);
}
int tot=0;
memset(dp2[0],0,sizeof(dp2[0]));
dp2[0][0]=1;
for(int v:g[u]){
++tot;
for(int x=0;x<2;x++){
dp2[tot][x]=dp2[tot-1][x];
}
for(int w=0;w<2;w++){
for(int y=0;y<2;y++){
dp2[tot][w^y]+=((LL)dp2[tot-1][w]*dp[v][y])%mod;
chan(dp2[tot][w^y]);
}
}
}
dp[u][0]=dp2[tot][1];
dp[u][1]=dp2[tot][0];
memset(dp2[tot+1],0,sizeof(dp2[tot+1]));
dp2[tot+1][0]=1;
int p=g[u].size();
for(int i=p-1;i>=0;i--){
int v=g[u][i];
for(int x=0;x<2;x++){
dp2[tot][x]=dp2[tot+1][x];
}
for(int w=0;w<2;w++){
for(int y=0;y<2;y++){
dp2[tot][w^y]+=((LL)dp2[tot+1][w]*dp[v][y])%mod;
chan(dp2[tot][w^y]);
}
}
tot--;
}
dp[u][0]+=dp2[1][1];
chan(dp[u][0]);
dp[u][1]+=dp2[1][0];
chan(dp[u][1]);
memset(dp1[0],0,sizeof(dp1[0]));
tot=0;
for(int v:g[u]){
++tot;
for(int x=0;x<2;x++){
for(int y=0;y<2;y++){
dp1[tot][x][y]=dp1[tot-1][x][y];
}
}
for(int w=0;w<2;w++){
for(int y=0;y<2;y++){
if(w==0){
dp1[tot][y][w]+=dp[v][y];
chan(dp1[tot][y][w]);
}
dp1[tot][w^y][w]+=((LL)dp1[tot-1][w][w^y]*dp[v][y])%mod;
chan(dp1[tot][w^y][w]);
}
}
}
dp[u][0]-=dp1[tot][1][0];
if(dp[u][0]<0) dp[u][0]+=mod;
dp[u][1]-=dp1[tot][0][0]+1;
if(dp[u][1]<0) dp[u][1]+=mod;
}
int main()
{
int n;
cin>>n;
for(int i=2;i<=n;i++){
int p;
scanf("%d",&p);
g[p].push_back(i);
}
for(int i=1;i<=n;i++) sort(g[i].begin(),g[i].end());
dfs(1);
cout<<((dp[1][0]+dp[1][1])%mod+mod)%mod<<endl;
}