FJOI 树的重心题解

来源:博客园  发布时间:2023-08-05 11:27:46 

从零开始暴切省选题

题意简述

给定一个 \(n\) 个点的树,每个点的编号从 \(1\) 至 \(n\),问这个树有多少不同的连通子树,和这个树有相同的重心。

分析

1 求重心

首先要明确重心的定义。题目中给出:删掉某点 \(i\) 后,若剩余 \(k\) 个连通分量,那么定义 \(d(i)\) 为这些连通分量中点的个数的最大值,所谓重心,就是使得 \(d(i)\) 最小的点 \(i\)。这句话翻译成人话就是:给定一棵无根树,令任意 \(u\) 为根,使得最大子树最小的 \(u\) 即为该树的重心。由这个定义,我们可以明确重心的求法。先假设节点 \(1\) 为根,对于每一个节点 \(u\),求它的所有子树大小,并取其最大值,与已存储的根的最大子树比较,如果节点 \(u\) 的最大子树更小,那么更新根节点 \(rt\leftarrow u\)。这在搜索回溯时处理即可。特别注意的是,搜索时因为程序需要钦定 \(1\) 为根节点,因此在递归至其他节点时要注意:如果以 \(u\) 为根,则还有一棵大小为 \(n-size_u\) 的子树(\(n\) 为节点数),这也要计入子树中。


(资料图)

inline void getr(int u, int fa) {    siz[u] = 1;    dp[u] = 0;    for(auto v : G[u]) {        if(v != fa) {            getr(v, u);            siz[u] += siz[v];            dp[u] = max(dp[u], siz[v]);        }    }    dp[u] = max(dp[u], n - siz[u]);    if(dp[rt] > dp[u] or rt == 0) {        rt = u;    }}

2 分类

求出重心后注意到题目提示 基于以上定义,一个树的重心可能会有一个或者两个。这提示我们要进行分类讨论。那么分类的标准是什么呢?注意到上文提到的重心的定义中出现了最大子树最小这一 \(min-max\) 条件,稍加推导就可以得出重心的一条重要性质:点 \(u\) 是树的重心 \(\Leftrightarrow\) \(u\) 的所有子树大小不超过 \(\lfloor\dfrac{n}{2}\rfloor\)(证明···自己找,网上很多的)。

然后就可以发现,如果有两个重心,那个两个重心所在的子树大小相等,均为 \(\dfrac{n}{2}\),所以设已求得的重心为 \(rt\),如果满足 \(size_rt\times2==n\),则树有两个重心;否则树只有一个重心。

3 DP与转移

根据题中求联通子树个数这个要求及答案对 \(1e4+7\) 取模可以猜测,解法应为树上 \(DP\)。因此考虑状态。在已知两个子树的情况下,如果要合并答案可以知道,应该用乘法原理令两个子树选取的节点数相乘再求和,所以 \(f\) 状态要能够记录选取的节点数这一关键信息。于是发现可以定义状态 \(f_{u,i}\) 表示以 \(u\) 为根的子树,取 \(i\) 个节点的方案数。其中取 \(i\) 个节点可以解释为这棵联通子树里有 \(i\) 个节点。

考虑在 \(dfs\) 过程中求解 \(f_{u,i}\)(以下默认 \(u\) 为当前子树的根节点)。先求 \(size\) 数组,可知现在已合并到 \(u\) 的子树里的节点个数最多为 \(size_u\),设要合并的子树根节点为 \(v\),则节点最多有 \(size_v\) 个。由上文的分析不妨把子树 \(u\) 和子树 \(v\) 分开枚举,分别枚举 \(i\) 和 \(j\),则可以更新 \(f_{u,i+j}\) 的答案。注意到由于更新时要用到原 \(f\) 数组的数据,于是用一个 \(res\) 数组暂存结果,等到全部转移完再复制到 \(f_u\) 中。

由乘法原理可得对于 \(res_{i+j}\) 有如下式子:

\[res_{i+j}=\sum_{i=1}^{size_u}\sum_{j=0}^{size_v}f_{u,i}\times f_{v,j}\]

而初始化条件即为 \(f_{u,0}=f_{u,1}=1\)。

4 答案求解

由 \(2\) 中的分类,以重心数量为依据分开处理。

  • 如果重心有两个则较为简单。首先求重心时已求得一个重心,考虑到重心性质:如果有两个重心则两个重心相邻,可以直接枚举与 \(rt\) 相邻的节点 \(v\),如果 \(size_v=size_rt=\dfrac{n}{2}\),则 \(v\) 为另一个重心。定义 \(3\) 中的 \(dfs\) 为 \(dfs(u,fa)\), \(u\) 为当前节点,\(fa\) 为父节点,则直接 \(dfs(rt,v),dfs(v,rt)\) 就可以求出对于两个子树分别成立的 \(f\) 数组。然后在 \(1\sim n\) 枚举所有可能的树大小, \(ans\) 就可以快速地求出了:
\[ans=\sum_{i=1}^{n}f_{rt,i}\times f_{v,i}\]
inline void dfsdptwort(int u, int v) {    memset(ddp, 0, sizeof ddp);    dfs1(u, v);    dfs1(v, u);    for(int i = 1; i <= n; i++) {        ans = (ans + ddp[u][i] * ddp[v][i]) % mod;    }}
  • 如果只有有一个重心,则枚举每个可能的树大小再重复一遍 \(dfs\) 中的求解过程就可以了。
inline void dfsdponlyrt(int u) {    memset(ddp, 0, sizeof ddp);    dfs1(u, 0);    for(int i = 1; i <= n; i++) {        memset(ddp[u], 0, sizeof ddp[u]);        s[u] = 1;        ddp[u][0] = ddp[u][1] = 1;        for(auto v : G[u]) {            for(int j = 1; j <= s[u] + s[v]; j++) {                tmp[j] = 0;            }            for(int j = 1; j <= s[u]; j++) {                for(int k = 0; k <= s[v]; k++) {                    if(k * 2 >= i) {                        break;                    }                    tmp[j + k] = (tmp[j + k] + ddp[u][j] * ddp[v][k] % mod) % mod;                }            }            s[u] += s[v];            for(int j = 1; j <= s[u]; j++) {                ddp[u][j] = tmp[j];            }        }        ans = (ans + ddp[u][i]) % mod;    }}

注意,由于有多组数据,每次数组和临时数据都要清空,尤其是用 \(vector\) 存储的邻接表用的 \(pushback\),尤其容易忘记。

总结

对于树上与子树或者数量有关问题,一般可以考虑树上 \(DP\),视情况可以在状态中存储子树大小,子树形态等信息,可以灵活运用计数原理,尤其在子树合并过程中

标签:

关闭

FJOI 树的重心题解

**从零开始**~~暴切~~省选题 题意简述给定一个$n$个点的树,每个点的更多

2023-08-05 11:27:46

美智库文章:惠誉为美国经济治理敲响警钟

参考消息网8月5日报道美国企业研究所网站8月3日刊登题为《美国信用评级更多

2023-08-05 10:42:30

用草编戒指的教程(如何用草做戒指简介介绍)

对于如何用草做戒指这个问题感兴趣的朋友应该很多,这个也是目前大家比更多

2023-08-05 10:08:08

esteem什么意思(esteem)

1、Esteem2、Esteem即依斯汀,它是尊重、尊敬的意思,是依斯汀品牌的经更多

2023-08-05 09:12:04

竞秀区检察院开展护航美丽河北建设专项监督宣传

保定晚报讯(通讯员宁欣蕊霍倩)近日,竞秀区检察院干警走进九华社区,开更多

2023-08-05 08:15:26

北京房山十渡景区千余名滞留人员乘火车平安撤离

央视网消息:据“中国铁路”消息,受持续降雨影响,为全力营救被困房山更多

2023-08-05 07:15:09

布罗克豪斯百科全书(布罗克豪斯F.A.)

想必现在有很多小伙伴对于布罗克豪斯,F A 方面的知识都比较想要了解,更多

2023-08-05 05:55:41

瑞丰银行(601528):8月4日北向资金增持171.84万股

8月4日北向资金增持171 84万股瑞丰银行。近5个交易日中,获北向资金增更多

2023-08-05 03:57:54

天际股份4.6亿收购新特化工背后:主力产品市场低

【大河财立方记者吴春波】改善公司业绩的方法有多种,锂电材料上市公司更多

2023-08-05 01:08:13

国际识局:时隔12年,美国信用评级再被降!三大原

日前,国际评级机构惠誉将美国长期外币发行人违约评级从AAA下调至AA+。更多

2023-08-04 22:25:49