• HDU5834Magic boy Bi Luo with his excited tree 树形dp


    分析:典型的两遍dfs树形dp,先统计到子树的,再统计从祖先来的,dp[i][0]代表从从子树回来的最大值,dp[i][1]代表不回来,id[i]记录从i开始到哪不回来

    吐槽:赛场上想到了状态,但是不会更新,而且据说这是一种典型的树形dp,还是太弱

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <cmath>
    #include <stdlib.h>
    using namespace std;
    typedef long long LL;
    const int N=1e5+10;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*hea,*tail;
    inline char Getchar() {
        if(hea==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(hea=buffer)+l;
        }
        return *hea++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    int T,n,a[N],head[N],tot,ret[N],dp[N][2],id[N],kase;
    struct Edge{
      int v,w,next;
    }edge[N<<1];
    void add(int u,int v,int w){
      edge[tot].v=v;
      edge[tot].w=w;
      edge[tot].next=head[u];
      head[u]=tot++;
    }
    void dfs(int u,int f){
      dp[u][0]=dp[u][1]=a[u];id[u]=-1;
      for(int i=head[u];~i;i=edge[i].next){
        int v=edge[i].v;if(v==f)continue;dfs(v,u);
        int tmp=max(0,dp[v][0]-2*edge[i].w);
        dp[u][1]+=tmp;
        if(dp[v][1]-edge[i].w>0){  
          if(dp[u][0]+dp[v][1]-edge[i].w>dp[u][1]){
            dp[u][1]=dp[u][0]+dp[v][1]-edge[i].w;
            id[u]=v;
          }
        }
        dp[u][0]+=tmp;
      }
    }
    void get(int u,int f,int x0,int x1){
      ret[u]=max(dp[u][0]+x1,dp[u][1]+x0);
      int w1=dp[u][1]+x0,w0=dp[u][0];
      if(w0+x1>=w1){
        w1=w0+x1;
        id[u]=f;
      }
      w0+=x0;
      for(int i=head[u];~i;i=edge[i].next){
        int v=edge[i].v;if(v==f)continue;
        int tmp,tmp0,tmp1;
        if(v!=id[u]){
           tmp=max(dp[v][0]-2*edge[i].w,0);
           tmp0=w0-tmp,tmp1=w1-tmp;
           get(v,u,max(0,tmp0-2*edge[i].w),max(0,tmp1-edge[i].w));
           continue;
        }
        tmp0=a[u]+x0,tmp1=a[u]+x1;
        for(int j=head[u];~j;j=edge[j].next){
          int to=edge[j].v;if(to==f||to==v)continue;
          tmp=max(0,dp[to][0]-2*edge[j].w);
          tmp1+=tmp;
          if(dp[to][1]-edge[j].w>0){
            if(tmp0+dp[to][1]-edge[j].w>tmp1)tmp1=tmp0+dp[to][1]-edge[j].w;
          }
          tmp0+=tmp;
        }
        get(v,u,max(0,tmp0-2*edge[i].w),max(0,tmp1-edge[i].w));
      }
    }
    int main(){
      T=read();
      while(T--){
        n=read();
        for(int i=1;i<=n;++i){
          head[i]=-1;a[i]=read();
        }
        tot=0;
        for(int i=1;i<n;++i){
          int u=read(),v=read(),w=read();
          add(u,v,w);add(v,u,w);
        }
        dfs(1,-1);
        get(1,-1,0,0);
        printf("Case #%d:
    ",++kase);
        for(int i=1;i<=n;++i)
          printf("%d
    ",ret[i]);
      }
      return 0;
    }
    View Code
  • 相关阅读:
    npx小工具
    2015 Multi-University Training Contest 1
    字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组
    AC自动机
    AC自动机
    区间合并 --- Codeforces 558D : Gess Your Way Out ! II
    暴力 + 贪心 --- Codeforces 558C : Amr and Chemistry
    计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task
    Ubuntu 16.04 安装mysql并设置远程访问
    数学 --- 高斯消元 POJ 1830
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5772915.html
Copyright © 2020-2023  润新知