• 动态规划:环套树


    普通的树有n个点和n-1条边

    如果在这个的基础上添加一条边,就变成了基环树

    对它进行dp的时候,考虑删除一条边转换成普通树

    对于每一棵环套树,先dfs找环

    找到环以后断环为链并将断开的两个点强制其中一个点为根且不选做一次树形DP,对另一个点做同样操作

    取两次结果最大值加入ans

    BZOJ1040的题意是这样的

    每个骑士都有且仅有一个自己最厌恶的骑士

    从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人

    并且,使得这支骑士军团最具有战斗力

    第一行包含一个正整数N,描述骑士团的人数。接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士

    整个图实际上是一个无向环套树森林

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<cstring>
     6 #define N 1000001
     7 #define ll long long 
     8 using namespace std;
     9 int n,cnt;ll ans,answer;
    10 int v[N],fa[N],head[N],to[N],next[N],ez[N],bh[N];
    11 ll dp[N][2],f[N][4];
    12 bool mark[N];
    13 void Ins(int a,int b)
    14 {cnt++;to[cnt]=b;next[cnt]=head[a];head[a]=cnt;}
    15 void init()
    16 {
    17     int i,k;
    18     scanf("%d",&n);
    19     for(i=1;i<=n;i++)
    20     {scanf("%d%d",&v[i],&k);Ins(k,i);fa[i]=k;}
    21 }
    22 void treedp(int x)
    23 {
    24     dp[x][1]=v[x];dp[x][0]=0;
    25     mark[x]=1;
    26     int i=head[x];
    27     while(i>0)
    28     {
    29         treedp(to[i]);
    30         dp[x][0]+=max(dp[to[i]][0],dp[to[i]][1]);
    31         dp[x][1]+=dp[to[i]][0];
    32         i=next[i];
    33     }
    34 }
    35 void finaldp()
    36 {
    37     int i,k;
    38     ans=0;
    39     f[1][1]=0;f[1][2]=0;
    40     f[1][0]=dp[bh[1]][1];
    41     f[1][3]=dp[bh[1]][0];
    42     for(i=2;i<=bh[0];i++)
    43     {
    44         k=bh[i];
    45         f[i][0]=f[i-1][1]+dp[k][1];
    46         f[i][1]=max(f[i-1][0],f[i-1][1])+dp[k][0];
    47         f[i][2]=f[i-1][3]+dp[k][1];
    48         f[i][3]=max(f[i-1][2],f[i-1][3])+dp[k][0];
    49     }
    50     ans=max(f[bh[0]][1],max(f[bh[0]][2],f[bh[0]][3]));
    51 }
    52 void solve()
    53 {
    54     int i,k,j,now;
    55     for(i=1;i<=n;i++)
    56     {
    57     if(mark[i])continue;
    58     bh[0]=0;
    59     k=i;
    60     while(!mark[k])
    61     {
    62         mark[k]=1;
    63         k=fa[k];
    64         ez[fa[k]]=k;
    65     }
    66     now=k;
    67     while(1)
    68     {
    69         i=head[k];
    70         dp[k][1]=v[k];
    71         while(i>0)
    72         {
    73             if(to[i]!=ez[k])
    74             {treedp(to[i]);
    75             dp[k][0]+=max(dp[to[i]][0],dp[to[i]][1]);
    76             dp[k][1]+=dp[to[i]][0];}
    77              i=next[i];
    78         }
    79         bh[0]++;bh[bh[0]]=k;
    80         k=fa[k];
    81         if(k==now)
    82         break;
    83     }
    84     finaldp();
    85     answer+=ans;
    86     }
    87     printf("%lld",answer);
    88 }
    89 int main()
    90 {
    91     init();
    92     solve();
    93     return 0;
    94 }
  • 相关阅读:
    19.1.30 [LeetCode 24] Swap Nodes in Pairs
    19.1.29 [LeetCode 23] Merge k Sorted Lists
    06_Python异常处理机制
    05_Python的文件操作
    04_Python中的35个关键字
    03_Python基础语法
    02_Python开发环境使用和PDB调试
    01_Python基础知识梳理
    socket post
    python_socket_cmd
  • 原文地址:https://www.cnblogs.com/aininot260/p/9627022.html
Copyright © 2020-2023  润新知