zoukankan      html  css  js  c++  java
  • bzoj1023 [SHOI2008]cactus仙人掌图

    题目描述:

    bz

    luogu

    题解:

    仙人掌$tarjan$。

    维护这个点向下走的最长链长度。

    搞到环的话拆开环用单调栈扫。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 50050;
    const int M = 100050;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int n,m,hed[N],cnt=1;
    struct EG
    {
        int to,nxt;
    }e[2*M];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    void build()
    {
        int a,b=-1,c;
        read(a);
        while(a--)
        {
            read(c);
            if(~b)ae(b,c),ae(c,b);
            b=c;
        }
    }
    int dp[N],dep[N],low[N],tim;
    int sta[N],tl,ans;
    int r[2*N],tr,s[N],h,l;
    void sol()
    {
        h = 1,l = 0;
        int lim = tr/2;
        for(int i=1;i<=lim;i++)
        {
            while(h<=l&&dp[r[s[l]]]+s[l]<=dp[r[i]]+i)l--;
            s[++l] = i;r[tr+i]=i;
        }
        for(int i=1;i<=tr;i++)
        {
            while(h<=l&&s[h]<=i)h++;
            while(h<=l&&dp[r[s[l]]]+s[l]<=dp[r[i+lim]]+i+lim)l--;
            s[++l] = i+lim;
            ans = max(ans,dp[r[i]]-i+dp[r[s[h]]]+s[h]);
        }
        for(int i=2;i<=tr;i++)
            dp[r[1]]=max(dp[r[1]],min(i-1,tr+1-i)+dp[r[i]]);
    }
    void tarjan(int u,int f)
    {
        dp[u] = 0;
        dep[u] = low[u] = ++tim;
        sta[++tl] = u;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==f)continue;
            if(!dep[to])
            {
                tarjan(to,u);
                low[u] = min(low[u],low[to]);
                if(low[to]>dep[u])
                {
                    ans = max(ans,dp[u]+dp[to]+1);
                    dp[u] = max(dp[u],dp[to]+1);
                    tl--;
                }else if(low[to]==dep[u])
                {
                    r[tr=1]=u;
                    while(sta[tl+1]!=to)r[++tr]=sta[tl--];
                    sol();
                }
            }else    low[u] = min(low[u],dep[to]);
        }
    }
    int main()
    {
        read(n),read(m);
        while(m--)build();
        tarjan(1,-1);
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    2015.7.23 开始记录一些学习情况
    poj 3299 java
    在线编辑~
    MATLAB加载数据来绘图《原创翻译Loading Data into MATLAB for Plotting》
    【转载】matlab的reshape函数的作用
    (转载)CUDA 6.0 安装及配置( WIN7 64位 / 英伟达G卡 / VS2010 )
    简单文本处理
    【转】CUDA与二维动态数组
    《转载》 cpp文件调用CUDA .cu文件实现显卡加速相关编程
    cuda_opencv之向量相加
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10815329.html
Copyright © 2011-2022 走看看