BZOJ1131 [POI2008]Sta 树DP

题目大意:给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大,N<=1000000
考虑一个点向其儿子转移对答案的影响。该子树内所有点深度-1,除该子树外的点深度+1,所以随便选一个根,预处理出深度和,然后全都转移一遍就可以。
自己的代码:

#include<cstdio> 
#include<algorithm> 
#define gm 1000001 
using namespace std; 
int n; 
struct e 
{ 
    int t; 
    e* n; 
    e(int t,e* n):t(t),n(n){} 
}*f[gm];
long long ans=0;
int nd; 
int sz[gm],fat[gm]; 
void dfs1(int x,int d) 
{ 
    sz[x]=1; 
    ans+=d; 
    for(e *i=f[x];i;i=i->n) 
    { 
        if(fat[x]==i->t) continue; 
        fat[i->t]=x; 
        dfs1(i->t,d+1); 
        sz[x]+=sz[i->t]; 
    } 
} 
void dfs2(int x,long long v) 
{ 
    if(ans<v||v==ans&&x<nd) ans=v,nd=x; 
    for(e *i=f[x];i;i=i->n) 
    { 
        if(fat[x]==i->t) continue; 
        dfs2(i->t,v-(sz[i->t]<<1)+n); 
    } 
} 
int main() 
{ 
    scanf("%d",&n); 
    int a,b; 
    for(int i=1;i<n;i++) 
    scanf("%d%d",&a,&b),f[a]=new e(b,f[a]),f[b]=new e(a,f[b]); 
    srand(114514); 
    int r=rand()%n+1; 
    nd=r; 
    dfs1(r,0); 
    dfs2(r,ans); 
    printf("%d",nd); 
    return 0; 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值