zoukankan      html  css  js  c++  java
  • BZOJ1791: [Ioi2008]Island 岛屿

    【传送门:BZOJ1791


    简要题意:

      给出一张有n个点的图,有n条双向边,长度为Li

      每个点只能走一次

      一个人可以到另一个连通块当且仅当现在所在的点所有与它相连的点都被走过,那么他就可以到另一个连通块的任意一个点

      这个人可以从任意一个点开始行走

      求出最大行走的边的长度和


    题解:

      就是求基环树森林的直径和

      对于一棵基环树,它的直径有三种情况:

      1.是环上的点的子树的直径

      2.是环上两个点的子树和+两个点的最大距离

      前者直接深搜,后者用单调队列维护求最大即可

      写一波手工栈就过去了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    struct node
    {
        int x,y,d,next;
    }a[2100000];int len,last[1100000];
    void ins(int x,int y,int d)
    {
        len++;
        a[len].x=x;a[len].y=y;a[len].d=d;
        a[len].next=last[x];last[x]=len;
    }
    int tot,s[1100000],X,Y,K;
    bool get_s(int x,int kk)
    {
        if(x==Y) return true;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(k==kk||k==(kk^1)||k==K||k==(K^1)) continue;
            if(get_s(y,k)==true){s[++tot]=k;return true;}
        }
        return false;
    }
    LL d[1100000],C[1100000],D[1100000],ans,mmax;
    bool bo[1100000];
    int v[1100000];
    /*
    void getc(int x)
    {
        v[x]=true;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(v[y]==true) continue;
            getc(y);
            if(bo[y]==false)
            {
                ans=max(ans,D[x]+D[y]+a[k].d);
                D[x]=max(D[x],D[y]+a[k].d);
            }
        }
    }*/
    int stack[1100000],cur[1100000],f[1100000];
    void getc(int x)
    {
        int tmp=0;stack[++tmp]=x;
        v[x]=0;cur[x]=last[x];
        while(tmp!=0)
        {
            x=stack[tmp];
            while(cur[x]!=0&&v[a[cur[x]].y]!=-1) cur[x]=a[cur[x]].next;
            if(cur[x]==0)
            {
                tmp--;
                if(f[x]!=0)
                {
                    ans=max(ans,D[f[x]]+D[x]+v[x]);
                    D[f[x]]=max(D[f[x]],D[x]+v[x]);
                }
                continue;
            }
            int y=a[cur[x]].y;cur[y]=last[y];stack[++tmp]=y;
            if(bo[y]==false)
            {
                v[y]=a[cur[x]].d;
                f[y]=x;
            }
            else v[y]=0;
            cur[x]=a[cur[x]].next;
        }
    }
    int q[2100000],p[1100000];
    int bak(int x){return (x-1)%tot+1;}
    LL getd(int x)
    {
        if(x<=tot) return d[x];
        else return d[tot+1]+d[x-tot];
    }
    LL solve()
    {
        d[1]=0;mmax=0;
        for(int i=1;i<=tot;i++)
        {
            d[i+1]=a[s[i]].d+d[i];
            s[i]=a[s[i]].y;
            bo[s[i]]=true;
        }
        s[++tot]=X;bo[X]=true;d[tot+1]=a[K].d+d[tot];
        ans=0;
        getc(s[1]);
        mmax=max(ans,mmax);
        int l=1,r=1;q[l]=1;
        for(int i=2;i<=2*tot;i++)
        {
            while(l<=r&&i-q[l]>=tot) l++;
            if(l<=r) mmax=max(mmax,D[s[bak(q[l])]]+D[s[bak(i)]]+getd(i)-getd(q[l]));
            while(l<=r&&D[s[bak(q[r])]]-getd(q[r])<=D[s[bak(i)]]-getd(i)) r--;
            q[++r]=i;
        }
        return mmax;
    }
    int fa[1100000];
    int findfa(int x)
    {
        if(fa[x]!=x) fa[x]=findfa(fa[x]);
        return fa[x];
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        len=1;memset(last,0,sizeof(last));
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=n;i++)
        {
            int x,d;
            scanf("%d%d",&x,&d);
            ins(i,x,d);ins(x,i,d);
            int fx=findfa(x),fy=findfa(i);
            if(fx==fy) p[fx]=len;
            else
            {
                fa[fx]=fy;
                if(p[fx]!=0) p[fy]=p[fx];
            }
        }
        for(int i=1;i<=n;i++) fa[i]=findfa(i);
        memset(bo,false,sizeof(bo));
        LL ans=0;
        memset(v,-1,sizeof(v));
        for(int i=1;i<=n;i++)
        {
            if(fa[i]==i)
            {
                tot=0;X=a[p[i]].x;Y=a[p[i]].y;K=p[i];
                get_s(X,0);
                ans+=solve();
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    apt-get install jdk
    progit-zh(Git中文文档)
    indexedDB bootstrap angularjs 前端 MVC Demo
    状态模式
    使用TypeConverter类
    wpf 全局异常捕获处理
    WPF 中的形状和基本绘图概述
    WPF设计自定义控件
    WPF快速入门系列(9)——WPF任务管理工具实现
    WPF快速入门系列(8)——MVVM快速入门
  • 原文地址:https://www.cnblogs.com/Never-mind/p/9744253.html
Copyright © 2011-2022 走看看