题解 CF1676G

这个题标签里有树形 dp ,但是其实用dfs已经足以解决这道题。

看这道题就可以发现这两道题其实是差不多的。

首先需要给两个节点之间建边,我们需要从 2n 循环输入。

因为他输入的是当前 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;
}

posted @ 2022-11-30 09:17  Tyrue  阅读(17)  评论(0编辑  收藏  举报