给定一个 n 个点的树,请求出一个结点,使得以这个结点为根时,所有结点的深度之和最大.一个结点的深度之定义为该节点到根的简单路径上边的数量.
思路:我们在一开始解的时候,如果我们要进行暴力求解我们的时间复杂度是O(n ^ 2),之后我们可以考虑对于样例1时,当前为根节点为1时
那么由这个方法我们可以通过两次dfs进行求解
第一次dfs,以1为根节点,自上而下求出每个节点的深度d,和每个节点的子树大小Size
第二次dfs,以1为根节点,自下而上,求出每个节点为根节点的总深度之和
最后遍历一遍dp数组找到深度之和最小的节点,时间复杂度O(n)
//求以谁为根 深度总和最大
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6 + 5;
vector<int>g[maxn];
int n;
ll dp[maxn];
ll d[maxn],Size[maxn];
//Size表示子树大小 d表示深度
void dfs1(int u, int fa){
Size[u] = 1;
d[u] = d[fa] + 1;
for(int i = 0; i < g[u].size(); i++){
int j = g[u][i];
if(j == fa)continue;
dfs1(j , u);
Size[u] += Size[j];
}
}
void dfs2(int u, int fa){
for(int i = 0; i < g[u].size(); i++){
int j = g[u][i];
if(j == fa)continue;
//自下而上
dp[j] = dp[u] + n - 2*Size[j];
dfs2(j , u);
}
}
int main(){
cin >> n;
for(int i = 1; i < n; i++){
int u,v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs1(1, 0);
for(int i = 1; i <= n; i++){
dp[1] += d[i];
}
dfs2(1, 0);
ll mx = -1, pos = -1;
for(int i = 1; i <= n; i++){
if(dp[i] > mx){
mx = dp[i];
pos = i;
}
}
cout << pos << '\n';
}