BZOJ1131: [POI2008]Sta

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

题解:记录每个点的深度,再根据根节点的深度和逐层推导出其他点的深度和。

我用的是BFS

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
int n,cnt,ans;
int head[1000010],next[2000010],to[2000010],fa[1000010],s[1000010];
ll f[1000010],g[1000010],siz[1000010];
queue<int> q;
void add(int a,int b)
{
    to[cnt]=b;
    next[cnt]=head[a];
    head[a]=cnt++;
}
int main()
{
    scanf("%d",&n);
    memset(head,-1,sizeof(head));
    int i,a,b,u;
    for(i=1;i<n;i++)
    {
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
    }
    q.push(1);
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        s[++s[0]]=u;
        siz[u]++;
        for(i=head[u];i!=-1;i=next[i])
        {
            if(to[i]!=fa[u])
            {
                fa[to[i]]=u;
                q.push(to[i]);
            }
        }
    }
    for(i=n;i>=2;i--)
    {
        siz[fa[s[i]]]+=siz[s[i]];
        f[fa[s[i]]]+=siz[s[i]]+f[s[i]];    //f[i]表示i的所有儿子到i的深度之和
    }
    g[1]=f[ans=1];
    for(i=2;i<=n;i++)
    {
        g[s[i]]=g[fa[s[i]]]+n-(siz[s[i]]<<1);    //g[i]表示所有点到i的距离之和,可由g[fa[i]]推出
        if(g[ans]<g[s[i]]||(g[ans]==g[s[i]]&&ans>s[i]))
        ans=s[i];
    }
    printf("%d",ans);
    return 0;
}
View Code

相关文章: