• bzoj1023: [SHOI2008]cactus仙人掌图


    仙人掌。

    仙人掌入门题。。不过入门都好难。。。

    题解好复杂。。

    总体来说,没有环的话,就是一棵树,很好求。

    如果有环的话,就找出这个环,用一个单调队列用环上俩个点对更新答案。(如果不用单调队列就O(n^2)超时)

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 3000000 + 10;
    
    int g[maxn],v[maxn],next[maxn],eid;
    int p[maxn],w[maxn],dis[maxn];
    int low[maxn],dfn[maxn],fa[maxn];
    int ring[maxn],cnt;
    int n,m,res;
    
    void addedge(int a,int b) {
        v[eid]=b; next[eid]=g[a]; g[a]=eid++;
        v[eid]=a; next[eid]=g[b]; g[b]=eid++;    
    }
    
    void getring() {
        int l=1,r=1;
        for(int i=1;i<=cnt;i++) ring[i+cnt]=ring[i];
        for(int i=1;i<=(cnt<<1);i++) {
            while(l<r && i-p[l]>(cnt>>1)) l++;
            while(l<r && w[r]<=dis[ring[i]]-i) r--;
            ++r;
            p[r]=i;
            w[r]=dis[ring[i]]-i;
            res=max(res,dis[ring[i]]+i+w[l]);    
        }
    }
        
    void dfs(int u) {
        low[u]=dfn[u];
        for(int i=g[u];~i;i=next[i]) 
            if(fa[v[i]] && v[i] !=fa[u]) 
                low[u]=min(low[u],dfn[v[i]]);
            else if(!fa[v[i]]) {
                fa[v[i]]=u;
                dfn[v[i]]=dfn[u]+1;
                dfs(v[i]);
                low[u]=min(low[u],low[v[i]]);
            }
            
        for(int i=g[u];~i;i=next[i]) {
            if(fa[v[i]]==u && low[v[i]]>dfn[u]) {
                res=max(res,dis[v[i]]+1+dis[u]);    
                dis[u]=max(dis[u],dis[v[i]]+1);
            }
            if(fa[v[i]]!=u && dfn[u]<dfn[v[i]]) {
                int p=v[i]; cnt=0;
                while(p!=fa[u]) {
                    ring[++cnt]=p;
                    p=fa[p];
                }
                getring();
                for(int j=1;j<cnt;j++) 
                    dis[u]=max(dis[u],dis[ring[j]]+min(j,cnt-j));
            }
        }
    }
    
    int main() {
        memset(g,-1,sizeof(g));
        scanf("%d%d",&n,&m);
        for(int i=1,a,b,x;i<=m;i++) {
            scanf("%d%d",&x,&a);
            for(int j=2;j<=x;j++) {
                scanf("%d",&b);
                addedge(a,b);
                a=b;
            }
        }
        fa[1]=-1;
        dfs(1);
        printf("%d
    ",res);
        return 0;
    }

  • 相关阅读:
    Linux 学习 之 bash
    C++ Knowledge series 4
    Linux 下, 安装Android Studio
    Java Knowledge series 1
    C++ Knowledge series 3
    Linux,MD5
    Using ASP.Net WebAPI with Web Forms
    CSS浮动属性Float到底什么怎么回事,下面详细解释一下
    什么是CSS清除浮动?
    Jquery ajax调用webservice总结
  • 原文地址:https://www.cnblogs.com/invoid/p/5634008.html
Copyright © 2020-2023  润新知