BZOJ1023: [SHOI2008]cactus仙人掌图

题意:求一棵仙人掌图的直径。

题解:戳ydc

http://ydcydcy1.blog.163.com/blog/static/21608904020131493113160/

代码:

int n,m,tot,head[maxn],dep[maxn],a[maxn],fa[maxn],q[maxn],low[maxn],dfn[maxn],f[maxn],ans;
struct edge{int go,next;}e[2*maxn];
inline void add(int x,int y)
{
    e[++tot]=(edge){y,head[x]};head[x]=tot;
    e[++tot]=(edge){x,head[y]};head[y]=tot;
}
inline void dp(int rt,int x)
{
    int k=dep[x]-dep[rt]+1;
    for1(i,k)a[i]=a[k+i]=x,x=fa[x];
    int l=1,r=0;q[1]=0;
    for1(i,k<<1)
    {
        while(l<=r&&i-q[l]>k>>1)l++;
        ans=max(ans,f[a[q[l]]]+f[a[i]]+i-q[l]);
        while(l<=r&&f[a[q[r]]]-q[r]<=f[a[i]]-i)r--;
        q[++r]=i;
    }
    for1(i,k-1)f[rt]=max(f[rt],f[a[i]]+min(k-i,i));
}
inline void dfs(int x)
{
    dfn[x]=low[x]=++m;
    for4(i,x)if(y!=fa[x])
    {
        if(!dfn[y]){fa[y]=x;dep[y]=dep[x]+1;dfs(y);low[x]=min(low[x],low[y]);}
        else low[x]=min(low[x],dfn[y]);
        if(dfn[x]<low[y])
        {  
         ans=max(ans,f[x]+f[y]+1);
         f[x]=max(f[x],f[y]+1);
        }
    }
    for4(i,x)if(fa[y]!=x&&dfn[x]<dfn[y])dp(x,y);
}

int main()

{

    freopen("input.txt","r",stdin);

    freopen("output.txt","w",stdout);

    n=read();m=read();
    for1(i,m)
    {
        int k=read(),x=read(),y;
        for1(i,k-1)y=read(),add(x,y),x=y;
    }
    m=0;
    dfs(1);
    cout<<ans<<endl;

    return 0;

}  

 

posted @ 2015-03-11 17:56  ZYF-ZYF  Views(240)  Comments(0Edit  收藏  举报