zoukankan      html  css  js  c++  java
  • bzoj1040: [ZJOI2008]骑士

     1 #include<cstdio>
     2 #include<iostream>
     3 #define M 1000001
     4 using namespace std;
     5 int head[M],next[M],u[M],n,v[M],fa[M],cnt,q[M],f1[M],xia[M],ans;
     6 long long dp[M][2],sum,f[M][4];
     7 void jia(int a1,int a2)
     8 {
     9     cnt++;
    10     next[cnt]=head[a1];
    11     head[a1]=cnt;
    12     u[cnt]=a2;
    13     return;
    14 }
    15 void tdp(int a1)
    16 {
    17     f1[a1]=1;
    18     dp[a1][0]=0;
    19     dp[a1][1]=v[a1];
    20     for(int i=head[a1];i;i=next[i])
    21       {
    22         tdp(u[i]);
    23         dp[a1][0]+=max(dp[u[i]][0],dp[u[i]][1]);
    24         dp[a1][1]+=dp[u[i]][0];
    25       }
    26     return;
    27 }
    28 int main()
    29 {
    30     scanf("%d",&n);
    31     for(int i=1;i<=n;i++)
    32       {
    33         int a1;
    34         scanf("%d%d",&v[i],&a1);
    35         jia(a1,i);
    36         fa[i]=a1;
    37       }
    38     for(int i=1;i<=n;i++)
    39       if(!f1[i])
    40         {
    41            q[0]=0;
    42            int k=i;
    43            for(;!f1[k];)
    44               {
    45                 f1[k]=1;
    46                 k=fa[k];
    47                 xia[fa[k]]=k;
    48               }
    49             int now=k;
    50             for(;;)
    51               {
    52                 dp[k][1]=v[k];
    53                 for(int j=head[k];j;j=next[j])
    54                   if(u[j]!=xia[k])
    55                    {
    56                      tdp(u[j]);
    57                      dp[k][0]+=max(dp[u[j]][0],dp[u[j]][1]);
    58                      dp[k][1]+=dp[u[j]][0];           
    59                    }
    60                 q[0]++;
    61                 q[q[0]]=k;
    62                 k=fa[k];
    63                 if(k==now)
    64                   break;
    65               }
    66             f[1][0]=dp[q[1]][1];
    67             f[1][1]=0;
    68             f[1][2]=0;
    69             f[1][3]=dp[q[1]][0];
    70             for(int j=2;j<=q[0];j++)
    71               {
    72                 f[j][0]=f[j-1][1]+dp[q[j]][1];
    73                 f[j][1]=max(f[j-1][1],f[j-1][0])+dp[q[j]][0];
    74                 f[j][2]=f[j-1][3]+dp[q[j]][1];
    75                 f[j][3]=max(f[j-1][2],f[j-1][3])+dp[q[j]][0];
    76               }
    77             sum+=max(f[q[0]][1],max(f[q[0]][2],f[q[0]][3]));
    78         }
    79     printf("%lld",sum);
    80     return 0;
    81 }

    如果把读入都建出边,这就是一个森林,每颗树可能有环,如果没有环的话,这就是一个简单的选儿子不能选爸爸的树形dp,由于n个点,n条边,所以最多是基环树森林,那就拆环,环上用

    两个数组跑,保证拆开的边上的两个点一定不被同时选。

  • 相关阅读:
    dfs介绍
    UVA11149 矩阵快速幂
    UVA1476 三分法
    漂亮的表达式!(不断补充)
    BC Round#33 B(10的18次方,快速乘法+快速幂取余)
    UVA 1639(组合数学)
    UVA 10612(数论找规律)
    小模板
    1589象棋(大模拟)
    bnuoj 29368 Check the Identity(栈)
  • 原文地址:https://www.cnblogs.com/xydddd/p/5229287.html
Copyright © 2011-2022 走看看