cf round 790 G. White-Black Balanced Subtrees

做题记录,如有不对,欢迎指出。

题目大意:有一棵树有n个节点,每一个节点会被上成黑或者白两种不同的颜色,黑用B表示,白用W表示,题目会给你两组数组,其中a数组为所有的父节点,b数组为每一个节点上的色。例如:

ai:112335,bi:wbbwwbw,如图所示。

如果每一个子树(即以a数组里边元素为树根的树)黑白节点个数相同,则称这个树为平衡树。求:题目给你的树中,有多少子树是平衡树?

题意解析:题目给的条件对于建树描述很抽象,刚开始建树的时候我一时没想明白,后来才知道,其实这个树是这么建的:因为树根是1,对于a数组里每一个父节点,从2开始,一一对应,就和例子里的一样,第一个元素对应1,第二个对应2....(1-1,1-2.....),由此每一个a数组去重以后,就是所有子树的根。

大体思路:看到这一题,第一个思路就是dfs遍历去统计每个根黑白是否相同,显然暴力虽简单,但是肯定tle。其实这一题是树形dp的模板题,想求节点黑白的数量,只需要直到子树的黑白数量即可,这样,我们就得到了一个转移方程:

dp(黑,index)=dp(黑,上一个index)白色同理。

为了得到线性复杂度,和代码的简洁,我们采用前向星链表。

简单提一下,前向星链表在这一题主要维护3个元素,第一个是边,第二个是邻接边,第三个是头节点的邻接边。回头在我博客中会详细记录一下前向星的具体原理。

这样,通过dfs遍历到叶子节点,然后一步一步递归dp记录当前黑白数量,最后判断黑白是否相等即可。

主要代码:

void add(int x, int y)
{
    e[cnt] = y;
    ne[cnt] = head[x];
    head[x] = cnt++;
}
void dfs(int a)
{
    for (int i = head[a]; i != -1; i = ne[i])
    {
        int t = e[i];
        dfs(t);
        f[a][1] += f[t][1];
        f[a][0] += f[t][0];
    }
    if (f[a][1] == f[a][0])ans++;
}
int main()
{
    cin >> test;
    while (test--)
    {
        memset(vis, 0, sizeof(vis));
        memset(head, -1, sizeof(head));
        memset(ne, 0, sizeof(ne));
        memset(e, 0, sizeof(e));
        memset(f, 0, sizeof(f));
        cnt = 0;
        cin >> n;
        ans = 0;
        for (int i = 2; i <= n; i++)
        {
            cin >> x;
            add(x, i);
        }
        for (int i = 1; i <= n; i++)
        {
            cin >> c;
            f[i][c == 'B'] = 1;
        }
        dfs(1);
        cout << ans << endl;
    }
}
 

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值