BZOJ 1131: [POI2008]Sta

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值