1 条题解
-
0
自动搬运
来自洛谷,原作者为

YoungNeal
**搬运于
2025-08-24 21:24:36,当前版本为作者最后更新于2018-03-23 12:54:21,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题解在博客食用效果更佳哦~YoungNeal
Solution第一想法是求出每个点到根节点的距离,然后 lca 瞎搞,但是会 T。
所以换 O(n) 的树形 dp。
不妨钦定以 1 为根。
记录 表示 i 与 i 的子树的结点个数之和。
定义 表示在点 i 开会的距离和。
定义 表示以 x 为根的子树中点的集合。显然
那么对于树上的非根节点 x,设它的父亲为 y。
所以转移方程
意思是,
① 考虑不在 中的点,它们到 x 的距离和是 它们到 y 的距离和加上
② 而对于那些在 中的点,它们到 x 的距离和就是 它们到 y 的距离和再减去
所以合并两式,
时间复杂度
// By YoungNeal #include<cstdio> #define N 50005 int d[N]; int f[N]; int n,cnt; int size[N]; bool vis[N]; int head[N]; struct Edge{ int to,nxt; }edge[N<<1]; void add(int x,int y){ edge[++cnt].to=y; edge[cnt].nxt=head[x]; head[x]=cnt; } void dfs1(int now){ size[now]=1; for(int i=head[now];i;i=edge[i].nxt){ int to=edge[i].to; if(d[to]) continue; d[to]=d[now]+1; dfs1(to); size[now]+=size[to]; } } void dfs(int now,int fa){ f[now]=f[fa]+n-2*size[now]; for(int i=head[now];i;i=edge[i].nxt){ int to=edge[i].to; if(to==fa) continue; dfs(to,now); } } signed main(){ scanf("%d",&n); for(int x,y,i=1;i<n;i++){ scanf("%d%d",&x,&y); add(x,y);add(y,x); } d[1]=1; dfs1(1); int maxn=0,idx=1; for(int i=1;i<=n;i++) maxn+=d[i]; maxn-=n; f[1]=maxn; for(int i=head[1];i;i=edge[i].nxt){ int to=edge[i].to; dfs(to,1); } for(int i=2;i<=n;i++){ if(f[i]<maxn) maxn=f[i],idx=i; } printf("%d %d",idx,maxn); return 0; }
- 1
信息
- ID
- 391
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者