NKOJ8663 彩色的树
_『果果』画了一棵
\color{blue}{五} ☆\color{orange}{彩} ☆\color{red}{斑} ☆\color{green}{斕} の树(。>∀<。),用1 \sim n 表示节点的编号,树上每个节点都有它对应的颜色c_i 。_记
f(x,y) 表示x 节点到y 节点的最短路径上经过节点的颜色种类数量,求:\sum_{i=1}^{n} \sum_{j=i+1}^{n} f(i,j)
看到熟悉的双层
但是如何拆分答案呢?
如果统计经过每一个点的路径会计算重复,不如直接对于每一种颜色分别计算经过这种颜色的路径数量。
但是依然不好直接计算。考虑正难则反,用总路径数量减去不经过这种颜色的路径数量。
因为树上的每一个点都是割点,所以剩下的路径只会在除去这些点外的连通块的内部。
不经过染色点的路径总数就是
观察后发现,除了包含树根的连通块,其余的连通块都是在一个染色点每一个子节点的子树中删去染色点的子树得到的。因此我们可以在树上 dfs,在每一个连通块所在子树的根节点更新答案。
又因为每个节点的颜色是唯一的,所以以它作为连通块顶部上方一个节点可以更新的答案也是唯一的,一次 dfs 即可完成。
使用类似『Tarjan』的思想,在树上 dfs 过程中动态维护全局信息,并在每个节点被访问和回溯时进行处理。
第一次访问到某个点
遍历完所有子节点后再将
dfs 过程完成后,用根节点的子树大小减去最终的