zoukankan      html  css  js  c++  java
  • BZOJ3037 创世纪[基环树DP]

    实际上基环树DP的名字是假的。。

    这个限制关系可以看成每个点有一条出边,所以就是一个内向基环树森林。

    找出每个基环树的环,然后对于树的部分,做DP,设状态选或不选为$f_{x,0/1}$,则

    $f_{x,0}=sumlimits_{yin son_x} max{f_{y,0},f_{y,1}}$

    $f_{x,1}=sumlimits_{yin son_x} max{f_{y,0},f_{y,1}}+[全选了f_{y,1}?]sumlimits_{yin son_x} max{f_{y,0}-f_{y,1}}$

    这个DP很简单,但是在环上很难处理,因为每个点取不取既和环上前一个点有关也和儿子有关,这个环上的点DP转移是有后效性的。

    采用基环树DP另一个常用的手段:断环成树,树形容易处理,避免后效性。断环时,应当注意断开的环上两个点相互影响的关系。

    比如此题,每一个点可能会影响后一个点的选择,分两种情况:此点不影响下一个点,则断开后,以此点为根做树形DP,那么两点互不影响,题目条件都成立。

    若考虑有影响,则需要这个点不选,让下一个点可以随便选儿子的两个状态较大值而不用担心没有指向他的不选的点。

    综上,断边后做两次DP即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define mst(x) memset(x,0,sizeof x)
     8 #define dbg(x) cerr << #x << " = " << x <<endl
     9 #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
    10 using namespace std;
    11 typedef long long ll;
    12 typedef double db;
    13 typedef pair<int,int> pii;
    14 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    15 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    16 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    17 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    18 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    19 template<typename T>inline T read(T&x){
    20     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    21     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    22 }
    23 const int N=1e6+7;
    24 struct thxorz{
    25     int head[N],nxt[N<<1],to[N<<1],tot;
    26     thxorz(){tot=1;}
    27     inline void add(int x,int y){
    28         to[++tot]=y,nxt[tot]=head[x],head[x]=tot;
    29         to[++tot]=x,nxt[tot]=head[y],head[y]=tot;
    30     }
    31 }G;
    32 int n;
    33 #define y G.to[j]
    34 int vis[N],to,rt,flag,ans,res,ban;
    35 void dfs(int x){//dbg(x);
    36     vis[x]=1;
    37     for(register int j=G.head[x];j;j=G.nxt[j])if(!(j&1)){
    38         if(vis[y])return rt=x,to=y,ban=j,void();
    39         else dfs(y);
    40     }
    41 }
    42 int f[N][2];
    43 void dp1(int x,int fa){
    44     vis[x]=1;int chosen=1;f[x][1]=1;
    45     for(register int j=G.head[x];j;j=G.nxt[j])if(y^fa&&j^ban&&j^(ban^1)){
    46         dp1(y,x);
    47         if(f[y][0]<f[y][1])f[x][0]+=f[y][1],f[x][1]+=f[y][1];
    48         else f[x][0]+=f[y][0],f[x][1]+=f[y][0],chosen=0;
    49     }
    50     if(chosen){
    51         int tmp=-N;
    52         for(register int j=G.head[x];j;j=G.nxt[j])if(y^fa&&j^ban&&j^(ban^1))MAX(tmp,f[y][0]-f[y][1]);
    53         f[x][1]+=tmp;
    54     }//dbg2(x,chosen);
    55 }
    56 void dp2(int x,int fa){
    57     int chosen=1;f[x][0]=0,f[x][1]=1;
    58     for(register int j=G.head[x];j;j=G.nxt[j])if(y^fa&&j^ban&&j^(ban^1)){
    59         dp2(y,x);
    60         if(f[y][0]<f[y][1])f[x][0]+=f[y][1],f[x][1]+=f[y][1];
    61         else f[x][0]+=f[y][0],f[x][1]+=f[y][0],chosen=0;
    62     }
    63     if(chosen&&x!=to){
    64         int tmp=-N;
    65         for(register int j=G.head[x];j;j=G.nxt[j])if(y^fa&&j^ban&&j^(ban^1))MAX(tmp,f[y][0]-f[y][1]);
    66         f[x][1]+=tmp;
    67     }
    68 }
    69 #undef y
    70 
    71 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    72     read(n);
    73     for(register int i=1,x;i<=n;++i)read(x),G.add(i,x);
    74     for(register int i=1;i<=n;++i,res=0)if(!vis[i]){
    75         dfs(i);
    76         dp1(rt,0);//不考虑断环之后根对断点有影响 
    77         res=_max(f[rt][0],f[rt][1]);
    78         dp2(rt,0);//考虑断环之后根对断点有影响(即不选根)
    79         MAX(res,f[rt][0]);
    80         ans+=res;
    81     }
    82     printf("%d
    ",ans);
    83     return 0;
    84 }
    View Code

    总结:基环树另一种常见做法:断环成树,考虑影响,做两次树形DP。

  • 相关阅读:
    codeforces 269B Greenhouse Effect
    codeforces 5C Longest Regular Bracket Sequence
    codeforces 225C Barcode
    codeforces 279C Ladder
    CodeForces 479E Riding in a Lift
    CodeForces 351A Jeff and Rounding
    POJ-1579-201308122106.txt
    表达式求值-201308081712.txt
    Encoding-201308072147.txt
    A + B Problem II201308072001.txt
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11814332.html
Copyright © 2011-2022 走看看