zoukankan      html  css  js  c++  java
  • EZOJ #80

    传送门

    分析

    经典的树型DP

    我们记录dp[i][0/1]表示i的子树中到i的长度分别为偶数和奇数的长度和

    dp2[i][0/1]则表示不在i的子树中的点到i的长度分别为偶数和奇数的长度和

    然后根据边的长度情况转移一下就可以了

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    long long dp[100100][2],dp2[100100][2];
    int sum[100100][2],sum2[100100][2];
    int val[200200],to[200200],head[200200];
    int nxt[200200],cnt,n,m;
    inline void add(int x,int y,int z){
        nxt[++cnt]=head[x];
        head[x]=cnt;
        to[cnt]=y;
        val[cnt]=z;
        nxt[++cnt]=head[y];
        head[y]=cnt;
        to[cnt]=x;
        val[cnt]=z;
    }
    inline void dfs1(int x,int fa){
        int i,j,k;
        for(i=head[x];i;i=nxt[i]){
          if(to[i]==fa)continue;
          dfs1(to[i],x);
          if(val[i]%2){
              dp[x][0]+=dp[to[i]][1];
              dp[x][0]+=1ll*sum[to[i]][1]*val[i];
              sum[x][0]+=sum[to[i]][1];
              dp[x][1]+=dp[to[i]][0]+1ll*val[i];
              dp[x][1]+=1ll*sum[to[i]][0]*val[i];
              sum[x][1]+=sum[to[i]][0]+1;
          }else {
              dp[x][0]+=dp[to[i]][0]+1ll*val[i];
              dp[x][0]+=1ll*sum[to[i]][0]*val[i];
              sum[x][0]+=sum[to[i]][0]+1;
              dp[x][1]+=dp[to[i]][1];
              dp[x][1]+=1ll*sum[to[i]][1]*val[i];
              sum[x][1]+=sum[to[i]][1];
          }
        }
        return;
    }
    inline void dfs2(int x,int fa){
        int i,j,k;
        long long t0=0,t1=0;
        int s0=0,s1=0;
        for(i=head[x];i;i=nxt[i]){
          if(to[i]==fa)continue;
          if(val[i]%2){
              t0+=dp[to[i]][1];
              t0+=1ll*sum[to[i]][1]*val[i];
              s0+=sum[to[i]][1];
              t1+=dp[to[i]][0]+1ll*val[i];
              t1+=1ll*sum[to[i]][0]*val[i];
              s1+=sum[to[i]][0]+1;
          }else {
              t0+=dp[to[i]][0]+1ll*val[i];
              t0+=1ll*sum[to[i]][0]*val[i];
              s0+=sum[to[i]][0]+1;
              t1+=dp[to[i]][1];
              t1+=1ll*sum[to[i]][1]*val[i];
              s1+=sum[to[i]][1];
          }
        }
        for(i=head[x];i;i=nxt[i]){
          if(to[i]==fa)continue;
          long long T0=t0,T1=t1;int S0=s0,S1=s1;
          if(val[i]%2){
              T0-=dp[to[i]][1];
              T0-=1ll*sum[to[i]][1]*val[i];
              S0-=sum[to[i]][1];
              T1-=dp[to[i]][0]+1ll*val[i];
              T1-=1ll*sum[to[i]][0]*val[i];
              S1-=sum[to[i]][0]+1;
              dp2[to[i]][0]+=dp2[x][1]+T1;
              dp2[to[i]][0]+=1ll*(sum2[x][1]+S1)*val[i];
              sum2[to[i]][0]+=sum2[x][1]+S1;
              dp2[to[i]][1]+=dp2[x][0]+1ll*val[i]+T0;
              dp2[to[i]][1]+=1ll*(sum2[x][0]+S0)*val[i];
              sum2[to[i]][1]+=sum2[x][0]+1+S0;
              dfs2(to[i],x);
          }else {
              T0-=dp[to[i]][0]+1ll*val[i];
              T0-=1ll*sum[to[i]][0]*val[i];
              S0-=sum[to[i]][0]+1;
              T1-=dp[to[i]][1];
              T1-=1ll*sum[to[i]][1]*val[i];
              S1-=sum[to[i]][1];
              dp2[to[i]][0]+=dp2[x][0]+1ll*val[i]+T0;
              dp2[to[i]][0]+=1ll*(sum2[x][0]+S0)*val[i];
              sum2[to[i]][0]+=sum2[x][0]+1+S0;
              dp2[to[i]][1]+=dp2[x][1]+T1;
              dp2[to[i]][1]+=1ll*(sum2[x][1]+S1)*val[i];
              sum2[to[i]][1]+=sum2[x][1]+S1;
              dfs2(to[i],x);
          }
        }
        return;
    }
    int main(){
        int i,j,k,x,y,z;
        scanf("%d%d",&n,&m);
        for(i=1;i<n;i++){
          scanf("%d%d%d",&x,&y,&z);
          add(x,y,z);
        }
        dfs1(1,0);
        dfs2(1,0);
        for(i=1;i<=m;i++){
          scanf("%d",&x);
          printf("%lld %lld
    ",dp[x][1]+dp2[x][1],dp[x][0]+dp2[x][0]);
        }
        return 0;
    }
  • 相关阅读:
    crunch--字典生成工具
    在LINUX上查询哪个用户从哪个IP登录,登录时间,执行了什么命令?
    关于jetbrains系列产品2018.1.5以后的使用(crack)方法
    vim 加密(crypt)文本文档
    ubuntu 安装 c语言的库函数man手册
    Ubuntu Desktop 编译 ffmpeg (简略的写写)
    统计php-fpm内存占用
    ffmpeg 视频 转 gif
    一条命令将windows下多个ts文件合并为一个ts文件
    CC攻击原理及防范方法
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/9901946.html
Copyright © 2011-2022 走看看