• bzoj1023: [SHOI2008]cactus仙人掌图


    题目就是算法啊

    求仙人掌图的直径也算是基本问题之一了吧。

    简单的想法就是dp,当y是割点,那么直接更新答案没有问题,也就是常规的treeDP求树的直径

    但是呢当构环了情况就会有些复杂。

    需要用到单调队列维护环里面的ans,不过f还是可以直接继承的。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    int n,m;
    struct node
    {
        int x,y,next;
    }a[2100000];int len,last[51000];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    
    int f[51000],ans;
    int d[110000],list[110000];
    int fa[51000],dep[51000];
    void DP(int rt,int bac)
    {
        int tot=dep[bac]-dep[rt]+1;
        for(int i=tot;i>=1;i--)
            d[i]=d[i+tot]=f[bac], bac=fa[bac];
        
        int head=1,tail=1;list[1]=1;
        for(int i=2;i<=tot*2;i++)
        {
            while(head<=tail&&i-list[head]>tot/2)head++;
            ans=max(ans,d[i]+d[list[head]]+i-list[head]);
            while(head<=tail&&d[list[tail]]-list[tail]<=d[i]-i)tail--;
            list[++tail]=i;
        }
        
        for(int i=1;i<=tot;i++)
            f[rt]=max(f[rt],d[i]+min(i-1,tot-i+1));
    }
    
    int z,dfn[51000],low[51000];
    void cactus(int x)
    {
        dfn[x]=low[x]=++z;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(dfn[y]==0)
            {
                fa[y]=x;
                dep[y]=dep[x]+1;
                cactus(y);
                low[x]=min(low[x],low[y]);
                
                if(dfn[x]<low[y])
                {
                    ans=max(ans,f[x]+f[y]+1);
                    f[x]=max(f[x],f[y]+1);
                }
            }
            else if(y!=fa[x])
                low[x]=min(low[x],dfn[y]);
        }
        
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(fa[y]!=x&&dfn[x]<dfn[y])DP(x,y);
        }
    }
    
    int main()
    {
        int T,x,y;
        scanf("%d%d",&n,&m);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&T);
            scanf("%d",&x);T--;
            while(T--)
            {
                scanf("%d",&y);
                ins(x,y);ins(y,x);
                x=y;
            }
        }
        
        z=0;
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        
        memset(fa,0,sizeof(fa));
        memset(dep,0,sizeof(dep));
        memset(f,0,sizeof(f));
        
        ans=0;cactus(1);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    BZOJ3672/UOJ7 [Noi2014]购票
    POJ3718 Facer's Chocolate Dream
    BZOJ1453:[WC]Dface双面棋盘
    BZOJ2957:楼房重建
    AtCoder Grand Contest 009 D:Uninity
    BZOJ2877:[NOI2012]魔幻棋盘
    BZOJ3065:带插入区间K小值
    BZOJ3489:A simple rmq problem
    浅谈主席树
    AtCoder Regular Contest 080 E:Young Maids
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8714549.html
Copyright © 2020-2023  润新知