Description
给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大
Input
给出一个数字N,代表有N个点.N<=1000000 下面N-1条边.
Output
输出你所找到的点,如果具有多个解,请输出编号最小的那个.
题解:
我们可以先计算以1为根它的深度之和,记为ans,然后把res表示下标记为1
然后树形dp从父亲向儿子转移
以父亲结点为根的答案即为ans,那么将根换成它的某一个儿子,那么儿子的子树的所有结点的深度都会-1,而其他结点深度则会+1,dfs转移即可
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define LL long long
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
const int MAXN = 1e6+10;
const int MOD = 1000000007;
const int INF = 0x3f3f3f3f;
struct node{ int v,nxt; }edge[MAXN<<1];
int head[MAXN],sz[MAXN],dep[MAXN],res=1,n,tot; LL ans;
inline void add(int u,int v){
edge[++tot].v=v; edge[tot].nxt=head[u]; head[u]=tot;
}
void dfs1(int u,int fa,int deep){
sz[u]=1; dep[u]=deep; ans+=dep[u];
for(int i=head[u];i;i=edge[i].nxt){
int v = edge[i].v;
if(v == fa) continue;
dfs1(v,u,deep+1);
sz[u] += sz[v];
}
}
void dfs2(int u,int fa,LL sum){
for(int i=head[u];i;i=edge[i].nxt){
int v = edge[i].v;
if(v == fa) continue;
LL tmp = sum-sz[v]+n-sz[v];
if(tmp > ans || (tmp == ans && v<res)) ans=tmp,res = v;
dfs2(v,u,tmp);
}
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d",&n);
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);
dfs1(1,0,1);
dfs2(1,0,ans);
printf("%d\n",res);
return 0;
}