题解 CF1676G
这个题标签里有树形 dp
,但是其实用dfs已经足以解决这道题。
看这道题就可以发现这两道题其实是差不多的。
首先需要给两个节点之间建边,我们需要从 2
到 n
循环输入。
因为他输入的是当前 2~n
的节点的父亲。
然后,我们将颜色读进来之后,把白色记为 1
,黑色记为 -1
。
这样计算的时候只要判断黑色的和白色的相加是否为 0
即可。
接着进行 dfs
,这里的 dfs
需要进入两个形参,
一个是当前节点的编号,一个是当前节点的父亲。
我们在里面循环找儿子的时候要保证不能往回走,所以要判断一下。
最终把节点的颜色和加起来,然后判断是否为0即可。
一定要记得初始化,因为 vector
用的是二维,所以要循环 clear
。
尽管不能真实的清除空间,但是我们这个题不需要清除空间。
只需要保证将所有的边都清除即可。
#include<cstdio>
#include<string.h>
#include<vector>
#include<iostream>
using namespace std;
const int N=4e3+10;
int T,n,ans;
vector<int> v[N];
int a[N],co[N],b[N];
void dfs(int x,int f){
b[x]=co[x];
for(int i=0;i<v[x].size();i++){
if(v[x][i]!=x && v[x][i]!=f){
dfs(v[x][i],x);
b[x]+=b[v[x][i]];
}
}
if(!b[x]){
ans++;
}
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
ans=0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++){
v[i].clear();
}
for(int i=2;i<=n;i++){
scanf("%d",&a[i]);
v[a[i]].push_back(i);
v[i].push_back(a[i]);
}
for(int i=1;i<=n;i++){
char c;
cin>>c;
if(c=='W'){
co[i]=1;
}else{
co[i]=-1;
}
}
dfs(1,0);
printf("%d\n",ans);
}
return 0;
}