dsu on tree 启发式合并算法

这篇博客翻译自Codeforces的一篇文章,讨论了如何处理树上的动态联通组件问题。文章首先引入了一个问题:在树的每个节点上,求子树中颜色出现的次数。接着,它提出了暴力求解方法,即通过两次深度优先搜索(DFS)来计算每个节点子树中特定颜色的节点数。

翻译自:http://codeforces.com/blog/entry/44351

我们先引入这样一个问题:

有一棵树,树上有很多结点,每个结点有一个颜色c,我们现在想知道树上每个结点的子树**(subtree)**,有多少个结点出现颜色c。子树的定义:该结点和其所有的孩子构成的树。
在这里插入图片描述
如上图:

  • 结点1子树:3个结点出现黄色,2个结点出现红色
  • 结点2子树:2个结点出现黄色,1个结点出现红色
  • 结点3子树:1个结点出现红色
  • 结点4子树:1个结点出现黄色
  • 结点5子树:1个结点出现红色
    我们现在抛出一个问题;
    树上每个结点的子树**(subtree)**,有多少个结点出现颜色黄色

暴力做法

不难想到,我们可以dfs遍历整个树,然后对结点再一次dfs(subtree),计算多少个点出现黄色,代码如下:

int cnt[maxn];
void add(int v, int p, int x){//v结点,p父节点
    cnt[ col[v] ] += x;
    for(auto u: g[v])
        if(u != p)
            add(u, v, x)
}
void dfs(int v, int p){
    add(v, p, 1);
    //现在cnt数组记录
    add(v, p, -1);
    for(auto u : g[v])
        if(u != p)
            dfs(u, v);
}
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值