换根DP
换根属于树形,是二次扫描,因为这类问题通常不会指定根结点,并且根节点的变化会对一些值,例如子结点深度和、点权和等产生影响。
通常需要二次,第一次来处理深度,以及点权和之类的问题,第二次开始动态规划。
令为当前结点,为当前结点的叶子结点。首先需要用来表示以为根的子树中的结点个数,并且有,那么这个通过一遍就可以办得到。
考虑状态转移,令表示以为根时,所有结点深度之和,那么进行换根,让为根,那么转移就是,那么这时候各结点的深度可以分为一下两种情况:
- 所有在的子树上的结点深度都减少,那么总深度之和就减少;
- 所有不在的子树上的结点深度都增加,那么总深度和就增加
那么状态转移方程就可以推出来了,。
于是第二遍处理这个东西就好,这样就能求出以所有结点为根节点的深度和了。
例题:[POI2008]STA-Station
代码:
// Problem: P3478 [POI2008]STA-Station
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3478
// Memory Limit: 125 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
const int N = 1E6 + 10, M = N * 2;
int Size[N];
int h[N], e[M], ne[M], idx;
int depth[N];
long long f[N];
int n;
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int dfs1(int u, int fa) {
Size[u] = 1;
if (fa == -1) depth[u] = 0;
else depth[u] = depth[fa] + 1;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == fa) continue;
int S = dfs1(j, u);
Size[u] += S;
}
return Size[u];
}
void dfs2(int u, int fa) {
for (int i = h[u]; i != -1; i = ne[i]) {
int v = e[i];
if (v == fa) continue;
f[v] = f[u] - 2 * Size[v] + n;
dfs2(v, u);
}
}
int main() {
scanf("%d", &n);
memset(h, -1, sizeof h);
for (int i = 1; i <= n - 1; i++) {
int a, b;
scanf("%d%d", &a, &b);
add(a, b), add(b, a);
}
dfs1(1, -1);
for (int i = 1; i <= n; i++) f[1] += depth[i];
//换根
//从u->v,在v子树上的深度减一,一共减去Size[v]
//不在v子树上的,深度都增加1,总共增加n - Size[v]
//那么从u到v答案变化,f[v] = f[u] - Size[v] + n - Size[v] = f[u] - 2 * Size[v] + n
dfs2(1, -1);
int res = 1;
long long cnt = 0;
for (int i = 1; i <= n; i++) {
if (f[i] > cnt) {
cnt = f[i];
res = i;
}
}
printf("%d\n", res);
return 0;
}
分类:
之前的比赛题目 / 算法从0开始
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端