NC15033 小G有一个大树
题目
题目描述
小G想要把自己家院子里的橘子树搬到家门口(QAQ。。就当小G是大力水手吧)
可是小G是个平衡性灰常灰常差的人,他想找到一个这个橘子树的平衡点。
怎么描述这棵树呢。。。就把它看成由一个个节点构成的树吧。结点数就
代表树重。
输入描述
多组数据输入输出,
第一行包含一个整数n(3<=n<=1000)代表树的结点的个数
以下n-1行描述(1-n)节点间的连接关系。
输出描述
输出两个个整数 x,num 分别代表树的平衡点,和删除平衡点后最大子树的结点数(如果结点数相同输出编号小的)。
示例1
输入
3 1 2 1 3
输出
1 1
题解
知识点:树形dp。
要求的不是整颗树的性质,而是某点相对于树的性质,直接枚举每个点求一次dp复杂度太高,考虑二次扫描与换根法。
先取一个点作为根dp一遍,求出每个点的子树的答案。再从头开始进行dp,假设父节点对于整个树的答案已经求出,可以通过这个答案结合子树答案,推断出子节点对于整棵树的答案。
回到题目上,要求的是节点数。于是取 作为根节点,第一遍dp求出每个节点的子树的节点数 ,转移方程看代码很基础。第二遍dp再从 出发求出节点答案 。考虑删除了父节点 ,会出现由 的各个子节点 对应的子树,以及 向上的一整棵树。于是 ,表示这些树中最多的节点数即是这个节点的答案。最终取 里最小的,并记录编号即可。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; int n; vector<int> g[1007]; int Size[1007], F[1007]; int ans, id; void dfs1(int u, int fa) { for (auto v : g[u]) { if (fa == v) continue; dfs1(v, u); Size[u] += Size[v]; } Size[u]++; } void dfs2(int u, int fa) { F[u] = n - Size[u]; for (auto v : g[u]) { if (v == fa) continue; dfs2(v, u); F[u] = max(F[u], Size[v]); } if (ans > F[u]) { ans = F[u]; id = u; } } int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); while (cin >> n) { for (int i = 1;i <= n;i++) g[i].clear(); for (int i = 1;i <= n - 1;i++) { int u, v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); } memset(Size, 0, sizeof(Size)); dfs1(1, 0); ans = 1e9; dfs2(1, 0); cout << id << ' ' << ans << '\n'; } return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16615709.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧