本文主要是介绍[POI2008] STA-Station/洛谷P3478(树形dp),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
[ P O I 2008 ] S T A − S t a t i o n ( 树形 d p ) \Huge{[POI2008] STA-Station(树形dp)} [POI2008]STA−Station(树形dp)
题目链接:[P3478 POI2008] STA-Station - 洛谷
文章目录
- 题意
- 思路
- 标程
题意
给定一个 n n n个点的树,请求出一个结点,使得以这个结点为根时,所有结点的深度之和最大。
一个结点的深度之定义为该节点到根的简单路径上边的数量。
数据范围
- 1 ≤ n ≤ 1 0 6 1 \le n \le 10^6 1≤n≤106
- 1 ≤ u , v ≤ n 1\le u,v \le n 1≤u,v≤n
思路
这是一道比较经典的树形dp问题。
假设以 x x x点作为根节点, y y y是 x x x的一个子节点;并令 b [ x ] b[x] b[x]为x节点的子节点个数, r e s [ x ] res[x] res[x]为以 x x x作为根节点时的深度之和, d e p [ x ] dep[x] dep[x]为x的深度。
那么我们可以计算出,若将跟节点从 x x x换为 y y y,那么可以得到: r e s [ y ] = r e s [ x ] − b [ y ] + ( n − b [ y ] ) res[y]=res[x] - b[y] + (n - b[y]) res[y]=res[x]−b[y]+(n−b[y])。
- − b [ y ] -b[y] −b[y]是因为其每个后代节点的度都减小 1 1 1。
- + ( n − b [ y ] ) +(n-b[y]) +(n−b[y])是因为 x x x的每个后代节点都增加 1 1 1。
并且,我们首先设 1 1 1为根节点,然后通过一次 d f s dfs dfs求出 d e p [ ] , b [ ] dep[~],b[~] dep[ ],b[ ];由每个点的深度我们可以求出 r e s [ 1 ] res[1] res[1]。然后再从1开始 d f s dfs dfs一次求出所有节点的 r e s [ ] res[~] res[ ]。最后比较哪个节点的 r e s [ ] res[] res[]值最大即可。
标程
#define int long long
const int N = 1e6 + 10; int n, b[N], dep[N], res[N];
vector<int> a[N];void dfs1(int x, int y) {dep[x] = dep[y] + 1;b[x] = 1;for(auto i : a[x]) {if(i == y) continue;dfs1(i, x);b[x] += b[i];}
}void dfs2(int x, int y) {for(auto i : a[x]) {if(i == y) continue;res[i] = res[x] + b[1] - 2 * b[i];dfs2(i, x);}
}void Solved() { cin >> n;for(int i = 1; i < n; i ++ ) {int x, y; cin >> x >> y;if(x == y) continue;a[x].push_back(y); a[y].push_back(x);}dfs1(1, 0);for(int i = 1; i <= n; i ++ ) res[1] += dep[i];dfs2(1, 0);int t = 1, mx = 0;for(int i = 1; i <= n; i ++ ) {if(res[i] > mx) t = i, mx = res[i];}cout << t << endl;
}
这篇关于[POI2008] STA-Station/洛谷P3478(树形dp)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!