树的深度(我觉得没毛病)

题干

给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大

Input

给出一个数字N,代表有N个点.N<=1000000 下面N-1条边.

Output

输出你所找到的点,如果具有多个解,请输出编号最小的那个.

Example
8

1 4

5 6

4 5

6 7

6 8

2 4

3 4



7

简单粗暴的题意,直接莽就完事了。
先搞个小点的例子试试水(我是把根节点的深度设为了0,其实你设1设几都没关系)
在这里插入图片描述
简单明了对吧,那我把根换一下呢?
在这里插入图片描述
我们会发现,我们把3作为根,那么包括3在内的3的子树的深度都减小了1,而1和2的深度都增加了1。那么规律是不是显而易见:

ans[儿砸]=(ans[爹]-siz[儿砸] )+(n-siz[儿砸] )

直接两遍dfs,第一遍处理完siz[]和ans[1](我们第一遍默认以1为根,当然你以别的为根也不是不行),第二遍再按找到的规律dfs更新答案即可

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=1000000+10;
long long head[maxn],len=0,ans[maxn],siz[maxn];
long long maxx;
int n,flag;
struct Edge{
    int next,to;
}edge[maxn<<1];
void Add(int u,int v){
    edge[++len].to=v;
    edge[len].next=head[u];
    head[u]=len;
}
void Dfs1(int u,int fa,int dep){
    siz[u]=1;
    for(int i=head[u];i;i=edge[i].next){
        int v=edge[i].to;
        if(v==fa) continue;
        Dfs1(v,u,dep+1);
        siz[u]+=siz[v];
        ans[1]+=dep+1;
    }
}
void Dfs2(int u,int fa){
    for(int i=head[u];i;i=edge[i].next){
        int v=edge[i].to;
        if(v==fa) continue;
        ans[v]=ans[u]+n-2*siz[v];
        if(ans[v]>maxx){
            maxx=ans[v];
            flag=v;
        }
        else if(ans[v]==maxx&&flag>v){
            flag=v;
        }
        Dfs2(v,u);
    }
}
int main(){
    cin>>n;
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        Add(u,v),Add(v,u);
    }
    Dfs1(1,0,0);
    maxx=ans[1],flag=1;
    Dfs2(1,0);
    cout<<flag<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/Zfio/p/12749655.html