dsu on tree 启发式合并算法

版权声明:欢迎转载,不要求署名~~~ https://blog.csdn.net/shadandeajian/article/details/82994975

翻译自: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);
}

猜你喜欢

转载自blog.csdn.net/shadandeajian/article/details/82994975