zoukankan      html  css  js  c++  java
  • BZOJ3832Rally题解

    一道思维神题....

    我们像网络流一样加入原点S,与汇点T

    用f[i]表示原点到i的最长路,用g[i]表示i到汇点的最长路

    f数组与g数组都可以dp求出来的

    接下来考虑如何通过这些信息来维护删除某个点的最长路

    用拓扑序来删点

    我们先将所有g数组加入一个集合中,

    每次删点是就先将所有该点的入边的点的f[i]+g[x]从集合中删掉

    然后此时集合中最大值就是删除这个点的最优解

    然后再将每个点的出边i的f[x]+g[i]加入集合中

    可以发现这个集合可以用堆来维护

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<cstring>
    # include<algorithm>
    # include<queue>
    using namespace std;
    const int mn = 500005;
    struct Grap{
        struct edge{int to,next;};
        edge e[mn*2];
        int head[mn],edge_max;
        void add(int x,int y)
        {
            e[++edge_max].to=y;
            e[edge_max].next=head[x];
            head[x]=edge_max;
        }
    }A,B;
    int deg[mn*2],n,m,a[mn*2];
    int f[mn*2],g[mn*2];
    void topolpgy()
    {
        int tail=1,head=0;
        for(int i=1;i<=n;i++)
            if(!deg[i]) a[++head]=i;
        //printf("%d %d
    ",tail,head);
        while(tail<=head)
        {
            int u=a[tail];
            tail++;
            for(int i=A.head[u];i;i=A.e[i].next)
            {
                deg[A.e[i].to]--;
                if(!deg[A.e[i].to]) a[++head]=A.e[i].to;
            }
        }
    }
    struct Heap{
        int heap[mn*2],mark[mn*2],top;
        void ins(int x)
        {
            if(mark[x])
            {
                --mark[x];
                return ;
            }
            heap[++top]=x;
            int t=top;
            while(t>1)
            {
                if(heap[t]>heap[t>>1])
                    swap(heap[t],heap[t>>1]),t>>=1;
                else
                    break;
            }
        }
        void del(int x)
        {
            mark[x]++;
        }
        void Pop()
        {
            heap[1]=heap[top--];
            int t=2;
            while(t<=top)
            {
                if( t<top && heap[t+1]>heap[t] )
                    t++;
                if(heap[t]>heap[t>>1])
                    swap(heap[t],heap[t>>1]),t<<=1;
                else
                    break;
            }
        }
        int Top()
        {
            while(mark[heap[1]])
                mark[heap[1]]--,Pop();
            return heap[1];
        }
    }T;
    int main()
    {
        int x,y;
        A.edge_max=0,B.edge_max=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            A.add(x,y),B.add(y,x);
            deg[y]++;
        }
        topolpgy();
        /*for(int i=1;i<=n;i++)
            printf("%d ",a[i]);*/
        int ans=0,ans_len=0x3f3f3f3f;
        for(int i=1;i<=n;i++)
        {
            int u=a[i];
            f[u]=max(f[u],1);
            for(int j=A.head[u];j;j=A.e[j].next)
                f[A.e[j].to]=max(f[A.e[j].to],f[u]+1);
        }
        for(int i=n;i>=1;i--)
        {
            int u=a[i];
            g[u]=max(g[u],1);
            for(int j=A.head[u];j;j=A.e[j].next)
                g[u]=max(g[u],g[A.e[j].to]+1);
        }
        /*for(int i=1;i<=n;i++)
            printf("%d:%d %d
    ",i,f[i],g[i]);*/
        for(int i=1;i<=n;i++)
            T.ins(g[i]);
        T.ins(0);
        for(int i=1;i<=n;i++)
        {
            int u=a[i];
            for(int j=B.head[u];j;j=B.e[j].next)
            {
                T.del(f[B.e[j].to]+g[u]);
               //printf("%d ",f[B.e[j].to]+g[u]);
            }
            //printf("
    ");
            T.del(g[u]);
            if(T.Top()<ans_len)
            {
                ans_len=T.Top(),ans=u;
                //printf("%d ",T.Top());
            }
            for(int j=A.head[u];j;j=A.e[j].next)
            {
                T.ins(f[u]+g[A.e[j].to]);
                //printf("%d ",f[u]+g[B.e[j].to]);
            }
            T.ins(f[u]);
            //printf("%d
    ",ans_len-1);
        }
        printf("%d %d",ans,ans_len-1);
        return 0;
    }
  • 相关阅读:
    linux shell获取用户输入
    yii2 笔记(1)
    yii2 数据库查询
    Yii2 环境配置生产环境和测试环境
    mysql 中find_in_set()和in()用法比较
    使用js提交form表单的两种方法
    base64编码的原理及实现
    浅析HTTP/2的多路复用
    Nginx 所使用的 epoll 模型是什么?
    git代码统计
  • 原文地址:https://www.cnblogs.com/logeadd/p/9606574.html
Copyright © 2011-2022 走看看