IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    BZOJ3743:[Coci2015]Kamp 树形dp

    wyfcyx发表于 2015-03-06 11:11:11
    love 0

    思路:

    首先发现如果根确定的话,我们要求的答案就是根和关键点们组成的虚树的边长之和的2倍减去根到所有关键点的距离最大值.

    这个应该不难理解.

    然后觉得虚树很难处理,就抛弃虚树,弄了一个繁琐至极的两遍dp.(这个我就不写是怎么dp的啦,大家应该都会.)

    然后看到某个题解说最上面说的那个东西bfs就行.

    如何呢?

    一个关键的性质:树上距离一个点最远的点必定是直径的一端!这个想想很显然.

    然后就简单了.

    下面是我的傻叉dp:

    #include
    #include
    #include
    #include
    #include
    using namespace std;
     
    #define INF 1ll<<59
     
    #define N 500010
    int head[N],next[N<<1],end[N<<1],len[N<<1];
    inline void addedge(int a,int b,int c){static int q=1;end[q]=b,next[q]=head[a],head[a]=q,len[q++]=c;}
    inline void make(int a,int b,int c){addedge(a,b,c),addedge(b,a,c);}
     
    bool c[N];
     
    long long max_dis[N],cnt[N],total_dis[N];
    inline void dp1(int x,int fa){
        for(int j=head[x];j;j=next[j])if(end[j]!=fa)dp1(end[j],x);
        cnt[x]=c[x],max_dis[x]=c[x]?0:-INF,total_dis[x]=0;
        for(int j=head[x];j;j=next[j])if(end[j]!=fa){
            cnt[x]+=cnt[end[j]];
            max_dis[x]=max(max_dis[x],max_dis[end[j]]+len[j]);
            total_dis[x]+=total_dis[end[j]]+(cnt[end[j]]?1ll:0ll)*len[j];
        }
    }
     
    long long re[N];
    long long seq[N],pre[N],suc[N],g[N];
    inline void dp2(int x,int fa,int fadis){
        long long real_total_dis,real_max_dis;
        if(x==1)real_total_dis=total_dis[x],real_max_dis=max_dis[x];
        else{
            real_total_dis=total_dis[x]+total_dis[fa]+(cnt[fa]?1ll:0ll)*fadis;
            real_max_dis=max(max_dis[x],max_dis[fa]+fadis);
        }
        re[x]=real_total_dis*2-real_max_dis;
         
        int num=0;
        for(int j=head[x];j;j=next[j])if(end[j]!=fa)seq[++num]=max_dis[end[j]]+len[j];
        pre[0]=suc[num+1]=-INF;
        for(int i=1;i<=num;++i)pre[i]=max(seq[i],pre[i-1]);
        for(int i=num;i>=1;--i)suc[i]=max(seq[i],suc[i+1]);
         
        num=0;
        for(int j=head[x];j;j=next[j])if(end[j]!=fa){
            ++num;
            g[end[j]]=max(pre[num-1],suc[num+1]);
        }
         
        int real_cnt=cnt[x];
        for(int j=head[x];j;j=next[j])if(end[j]!=fa){
            total_dis[x]=real_total_dis-total_dis[end[j]];
            if(cnt[end[j]])total_dis[x]-=len[j];
            max_dis[x]=g[end[j]];
            if(x!=1)max_dis[x]=max(max_dis[x],max_dis[fa]+fadis);
            if(c[x])max_dis[x]=max(max_dis[x],0ll);
            cnt[x]=real_cnt-cnt[end[j]]+cnt[fa];
             
            dp2(end[j],x,len[j]);
        }
    }
     
    int main(){
        int n,m;scanf("%d%d",&n;,&m;);register int i,j;
        if(m==0){puts("0");return 0;}
        int a,b,x;
        for(i=1;i<=n;++i)printf("%lld\n",re[i]);
        return 0;
    }


沪ICP备19023445号-2号
友情链接