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