main
黄海 2 years ago
parent 7c81f9f332
commit 5ec8f622dc

@ -0,0 +1,50 @@
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
#define int long long
#define endl "\n"
struct edge {
int to, nxt;
} e[N << 1];
int n, cnt, id;
int head[N];
int ans;
int f[N], dep[N], size[N];
inline void add(int u, int v) {
e[++cnt].nxt = head[u];
head[u] = cnt;
e[cnt].to = v;
}
void dfs1(int x, int fa) {
size[x] = 1;
dep[x] = dep[fa] + 1;
for (int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if (y == fa) continue;
dfs1(y, x);
size[x] += size[y];
}
}
void dfs2(int x, int fa) {
for (int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if (y == fa) continue;
f[y] = f[x] + n - 2 * size[y];
dfs2(y, x);
}
}
signed main() {
cin >> n;
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
add(u, v), add(v, u);
}
dfs1(1, 0);
for (int i = 1; i <= n; i++) f[1] += dep[i];
dfs2(1, 0);
for (int i = 1; i <= n; i++)
if (ans < f[i]) ans = f[i], id = i;
cout << id << endl;
}

@ -1,17 +1,18 @@
## 换根 $dfs$ 专题
## 换根$DP$
换根$DP$,又叫二次扫描,是树形$DP$的一种。
其相比于一般的树形$DP$具有以下特点:
- 以树上的不同点作为根,其解不同
- 故为求解答案,不能单求某点的信息,需要求解每个节点的信息
- 故无法通过一次搜索完成答案的求解,因为一次搜索只能得到一个节点的答案
- 以树上的不同点作为根,其解不同
- 故为求解答案,不能单求某点的信息,需要求解每个节点的信息
- 故无法通过一次搜索完成答案的求解,因为一次搜索只能得到一个节点的答案
难度也就要比一般的树形$DP$高一点。
### 题单
#### **[$POI2008$ $STA-Station$](https://www.luogu.com.cn/problem/P3478)**
#### 题单
$[POI2008]STA-Station$
> **题意**:给定一个$n$个点的无根树,问以树上哪个节点为根时,其所有节点的深度和最大?
**深度**:节点到根的简单路径上边的数量
@ -24,21 +25,24 @@ $[POI2008]STA-Station$
所以我们考虑在第二次搜索时就完成所有节点答案的统计——
- ① 我们假设第一次搜索时的根节点为$1$号节点,则此时只有$1$号节点的答案是已知的。同时第一次搜索可以统计出所有子树的大小。
- ② 第二次搜索依旧从$1$号节点出发,若$1$号节点与节点$x$相连,则我们考虑能否通过$1$号节点的答案去推出节点$x$的答案。
- ③ 我们假设此时将根节点换成节点$x$,则其子树由两部分构成,第一部分是其原子树,第二部分则是$1$号节点的其他子树(如下图)。
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202401090926001.png)
![](https://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/202401090958197.png)
- ④ 根从$1$号节点变为节点$x$的过程中,我们可以发现第一部分的深度降低了$1$,第二部分的深度则上升了$1$,而这两部分节点的数量在第一次搜索时就得到了。
- ⑤ 故得到递推公式:
$$ans[v]=ans[u]-siz[v]+(siz[1]-siz[v]),fa[v]=u$$
化简一下,就是
$$ans[v]=ans[u]+siz[1]-2\times siz[v]$$
故得到递推公式:
$$f[v]=f[u]-siz[v]+(siz[1]-siz[v]),fa[v]=u$$
简化一下就是
$$f[v]=f[u]+siz[1]-2\times siz[v]=f[u]+n-2\times siz[v]$$
**总结与进阶**
由此我们可以看出换根$DP$的套路:
- 指定某个节点为根节点。

Loading…
Cancel
Save