给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大
Input
给出一个数字N,代表有N个点.N<=1000000 下面N-1条边.
Output
输出你所找到的点,如果具有多个解,请输出编号最小的那个.
Sample Input8 1 4 5 6 4 5 6 7 6 8 2 4 3 4Sample Output7
分析:这个题如果以每个根dfs的话肯定会超时。
定义size[i]为以i为根的子树的节点数,f[i]为以为根的树的所有点的深度
我们不难发现f[v] = f[u] + n - 2 * size[v]
把根由u变成v,v的子树节点所有的深度都减1,一共减少了size[v],v以上一共有n-size[v]个点,深度都加1,加了n-size[v]所以一共是n-2*size[v]
所以我们先dfs把每个点的深度和子树大小跑出来,再跑一遍dfs把f[i]算出来,最后遍历一遍f[i]就可以了
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1000010; 4 struct edge 5 { 6 int to,nxt; 7 }e[maxn<<1]; 8 int n,cnt,id; 9 int head[maxn]; 10 long long ans; 11 long long f[maxn],d[maxn],size[maxn], t; 12 inline void Add(int u,int v) 13 { 14 e[++cnt].nxt=head[u]; 15 head[u]=cnt; 16 e[cnt].to=v; 17 } 18 void Dfs1(int x,int fa) 19 { 20 size[x]=1;d[x]=d[fa]+1; 21 for(int i=head[x];i;i=e[i].nxt) 22 { 23 int y=e[i].to; 24 if(y==fa) continue; 25 Dfs1(y,x); 26 size[x]+=size[y]; 27 } 28 } 29 void Dfs2(int x,int fa) 30 { 31 for(int i=head[x];i;i=e[i].nxt) 32 { 33 int y=e[i].to; 34 if(y==fa) continue; 35 f[y]=f[x]+n-2*size[y]; 36 Dfs2(y,x); 37 } 38 } 39 int main() 40 { 41 scanf("%d",&n); 42 for(int i=1;i<n;i++) 43 { 44 int u,v;scanf("%d%d",&u,&v); 45 Add(u,v),Add(v,u); 46 } 47 Dfs1(1,0); 48 for(int i=1;i<=n;i++) f[1]+=d[i]; 49 Dfs2(1,0); 50 for(int i=1;i<=n;i++) if(ans<f[i]) ans=f[i],t=i; 51 printf("%d",t); 52 return 0; 53 }