平衡树

题目大意为,给你一颗树,告诉上面的节点,分为黑和白,求有多少子树上面的黑和白节点是相等的;
思路:首先通过邻接表将树记录下来,再从跟节点开始,通过递归访问每个节点,同时记录当前节点是否来过,如果没来过,则不断访问他的子节点,当找到底之后,判断从根节点到这个节点的黑白节点数量,看是不是平衡树

点击查看代码
vector<int> adj[N];
int c[N], a[N], b[N]; // c数组存储节点的颜色,a数组存储黑色,b数组存储白色
int vis[N];			  //
int ans;			  // 记录平衡子树的数量
void dfs(int from)
{
	vis[from] = 1;
	if (c[from] == 'B') // 如果当前节点是黑色,a数组加1
	{
		a[from]++;
	}
	if (c[from] == 'W') // 白色b+1
	{
		b[from]++;
	}
	for (int i = 0; i < adj[from].size(); i++) // 遍历当前节点的所有子节点
	{
		if (!vis[adj[from][i]]) // 如果子节点未被访问过
		{
			dfs(adj[from][i]);			// 递归访问子节点
			a[from] += a[adj[from][i]]; // 累加子节点的黑色节点数
			b[from] += b[adj[from][i]]; // 累加子节点的白色节点数
		}
	}
	if (a[from] == b[from]) // 如果当前子树的黑色节点数等于白色节点数,平衡子树数量加1
	{
		++ans;
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cout << fixed << setprecision(15);

	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		for (int i = 0; i < n; ++i)
		{
			adj[i].clear();
		}
		memset(vis, 0, sizeof(vis));
		memset(b, 0, sizeof(b));
		memset(a, 0, sizeof(a)); // 初始化
		ans = 0;

		vector<int> a(n);
		for (int i = 1; i < n; ++i)
		{
			cin >> a[i]; // 输入第i个节点的父节点
			--a[i];
			adj[a[i]].push_back(i); // 构建邻接表
		}
		string s;
		cin >> s;
		for (int i = 0; i < n; ++i)
		{
			c[i] = s[i];
		}
		dfs(0); // 从根节点开始进行深度优先搜索
		cout << ans << '\n';
	}
	return 0;
}



posted @ 2024-07-25 15:05  台州第一深情  阅读(11)  评论(0编辑  收藏  举报