BZOJ 1023: [SHOI2008]cactus仙人掌图 (仙人掌,树形DP,单调队列)

对于树边直接转移,然后按照套路拆环,在环上做一个单调队列 DP.   

一种方案虽然在一个换上可能算不了,但是一定可以在另一个环上计算到. 

仙人掌上 DP 的套路就是遇到树边就按照树上做,遇到环就拆环,做一个环形 DP.    

code: 

#include <bits/stdc++.h>  
#define N 200006 
#define M 400006   
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
int ans,n,m; 
int hd[N],to[M],nex[M],edges,tim,top;    
int tot,a[N],q[N],fa[N],low[N],dfn[N],dep[N],f[N];   
void add(int u,int v) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;   
} 
void calc(int root,int x) 
{          
    top=dep[x]-dep[root]+1;    
    for(int i=x;i!=root;i=fa[i])  
        a[top--]=f[i];     
    a[1]=f[root];      
    top=dep[x]-dep[root]+1;    
    for(int i=1;i<=top;++i) a[i+top]=a[i];    
    int l=1,r=1;     
    q[r]=1;    
    for(int i=2;i<=top*2;++i) 
    {
        while(l<=r&&i-q[l]>top/2) ++l;     
        ans=max(ans,a[q[l]]+a[i]+i-q[l]);    
        while(l<=r&&a[q[r]]-q[r]<=a[i]-i) --r;  
        q[++r]=i; 
    }
    for(int i=2;i<=top;++i)  
        f[root]=max(f[root],a[i]+min(top-i+1,i-1));    
}
void dfs(int x,int ff) 
{
    dfn[x]=low[x]=++tim;    
    fa[x]=ff,dep[x]=dep[ff]+1;     
    for(int i=hd[x];i;i=nex[i]) {   
        int v=to[i]; 
        if(v==ff) continue;   
        if(!dfn[v]) 
        {
            dfs(v,x);    
            low[x]=min(low[x],low[v]);  
        }  
        else low[x]=min(low[x],dfn[v]);         
        if(dfn[x]<low[v]) 
        {
            ans=max(ans,f[x]+f[v]+1);  
            f[x]=max(f[x],f[v]+1); 
        }
    }   

    for(int i=hd[x];i;i=nex[i]) 
    {
        int v=to[i]; 
        if(v==ff) continue;   
        if(fa[v]!=x&&dfn[x]<dfn[v]) 
            calc(x,v);    
    }
}
int main() 
{ 
    // setIO("input");         
    scanf("%d%d",&n,&m); 
    for(int i=1;i<=m;++i) 
    {
        int k,last;  
        scanf("%d%d",&k,&last);   
        for(int j=1;j<k;++j) 
        {
            int x;  
            scanf("%d",&x); 
            add(x,last),add(last,x);  
            last=x; 
        }
    }
    dfs(1,0); 
    printf("%d\n",ans);  
    return 0; 
}

  

posted @ 2020-03-29 23:40  EM-LGH  阅读(129)  评论(0编辑  收藏  举报