zoukankan      html  css  js  c++  java
  • 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
    ",ans);  
        return 0; 
    }
    

      

  • 相关阅读:
    angular读书笔记(三)
    angular读书笔记(二)
    angularjs读书笔记(一)
    angular和web前端的一些细节
    angular的service
    angular学习之directive
    最近学的twig
    最近学的grunt
    今天学的angularJS
    android即时通讯开发笔记(一)绪论~实现用户登录,自动登录,注销功能
  • 原文地址:https://www.cnblogs.com/guangheli/p/12595966.html
Copyright © 2011-2022 走看看