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\n",ans);
    return 0;
}

 

posted @ 2018-04-04 08:32  AKCqhzdy  阅读(211)  评论(0编辑  收藏  举报