树上统计问题【一】

在树上,对于每个点 \(u\),设 \(c(u)\) 为点对 \((s, t)\) 的数量,满足 \(s \ne t\),且 \(s\)\(t\) 的路径经过点 \(u\)

要求用总共 \(\mathcal O(n)\) 的复杂度,求出 \(c\) 数组。

我们可以把要求的 \(c(u)\) 转化成:删除与点 \(u\) 相关联的所有边后,有多少个点对不再联通。

只要点数 \(n \ne 1\),这样删除就一定形成 \(k \ge 2\) 个连通块。设大小分别为 \(s_1, s_2, \ldots,s_k\),那么答案就是 \(s_1 \times (n - s_1) + s_2 \times (n - s_2) + \ldots + s_k \times (n - s_k)\)

给原树随便定个根,那么形成的连通块分别是:

  • \(u\) 孤立点。构成 \(1\) 个连通块。
  • \(u\) 的每个儿子对应的子树。一个儿子,对应一个子树,对应 \(1\) 个连通块。
  • \(u\) 的所有祖先。如果 \(u\) 不是根,这里就构成 \(1\) 个连通块。

树上一次 dfs,上面三种连通块的大小都能很方便得到。于是做到总复杂度 \(\mathcal O(n)\)

例题:https://www.luogu.com.cn/problem/P4630

该题先构建广义圆方森林,然后圆点设权 \(-1\),方点设权为点双连通分量的大小后,再乘上对应的 \(c(u)\) 求和为答案。

因为是广义圆方森林,应该对每棵树分别统计答案,将每棵树的大小作为上面的 \(n\),而不是总点数。

而且这个题要统计的 \(s\)\(t\) 都要求是圆点,所以统计连通块大小时只应统计圆点。

【拓展】

无向图 上,对于每个点 \(u\),设 \(c(u)\) 为点对 \((s, t)\) 的数量,满足 \(s \ne t\),且 \(s\)\(t\)所有路径 都经过点 \(u\)

要求用总共 \(\mathcal O(n)\) 的复杂度,求出 \(c\) 数组。

其实就是这个题 https://www.luogu.com.cn/problem/P3469

题目还是等价于断开 \(u\) 的连边后 \(s\)\(t\) 不再联通。

这次,我们构建 dfs 搜索树,然后在树上 dfs,接着沿用上面的做法。但是,删除点 \(u\) 的连边后,以 \(u\) 的某个儿子 \(v\) 为根的子树可能跟 \(u\) 的祖先是连着的。

所以当且仅当 \(\mathrm{dfn}[v] \ge \mathrm{low}[u]\) 的时候,我们再将以 \(v\) 为根的子树当成一个连通块处理;否则,这个子树应该和 \(u\) 的祖先算在一个连通块中。

tarjan 同时统计就可以啦。

posted @ 2023-03-23 01:15  dbxxx  阅读(65)  评论(0编辑  收藏  举报