zoukankan      html  css  js  c++  java
  • 动态规划:环套树

    普通的树有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 }
  • 相关阅读:
    Git 分支管理
    Kubernetes 中文文档
    Docker 命令大全
    Redis 常用命令 大全
    Docker 资源汇总
    Docker 安装 Redis
    JavaScript闭包
    CSS选择器
    JavaScript类型转换
    javascript字符串处理方法
  • 原文地址:https://www.cnblogs.com/aininot260/p/9627022.html
Copyright © 2011-2022 走看看