zoukankan      html  css  js  c++  java
  • 【BZOJ3887】【Usaco2015 Jan】Grass Cownoisseur Tarjan+Spfa

    我们可以看出这个东西可以缩点成DAG,因为我们在所称的点里用特技的话,要么没用,要么削弱自己对点的收割能力与边的联通权,所以我们缩完点之后在图上枚举反向的变,因为我们只可能反向一条边,而且我们知道在这条边上走的方向,那么我们一定是在边终点回去,在边起点来,因为一来一回的这两条路径一定没有交叉所以我们找着两条路径的最大值,我们跑两边SPFA就好了,(一边正向,一边反向)。

    注意在无向图Tarjan时要穷举,因为一个点可能走不完。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 100005
    using namespace std;
    inline int read()
    {
        int sum=0;
        char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')
        {
            sum=(sum<<1)+(sum<<3)+ch-'0';
            ch=getchar();
        }
        return sum;
    }
    inline int Min(int x,int y)
    {
        return x<y?x:y;
    }
    inline int Max(int x,int y)
    {
        return x>y?x:y;
    }
    int dfn[MAXN],low[MAXN],when,stack[MAXN],top;
    struct Tr
    {
        int to,next,w;
    }C[MAXN],c[MAXN<<1];
    int Head[MAXN],T,head[MAXN],t;
    bool in[MAXN];
    inline void Add(int x,int y)
    {
         C[++T].to=y;
         C[T].next=Head[x];
         Head[x]=T;
    }
    int belong[MAXN],sum[MAXN],num;
    int n,m;
    void Tarjan(int x)
    {
        low[x]=dfn[x]=++when;
        stack[++top]=x;
        in[x]=1;
        for(int i=Head[x];i;i=C[i].next)
        {
            int y=C[i].to;
            if(!dfn[y])
            {
                Tarjan(y);
                low[x]=Min(low[x],low[y]);
            }
            else if(in[y])
                low[x]=Min(low[x],dfn[y]);
        }
        if(dfn[x]==low[x])
        {
            int j;
            num++;
            do
            {
                j=stack[top--];
                in[j]=0;
                belong[j]=num;
                sum[num]++;
            }while(j!=x);
        }
    }
    inline void add(int x,int y,int z)
    {
        c[++t].to=y;
        c[t].next=head[x];
        head[x]=t;
        c[t].w=z;
    }
    struct E
    {
        int x,y;
    }e[MAXN];
    int sz;
    inline void buildnew()
    {
        for(int x=1;x<=n;x++)
        {
            for(int i=Head[x];i;i=C[i].next)
            {
                int y=C[i].to;
                if(belong[x]==belong[y])continue;
                e[++sz].x=belong[x];
                e[sz].y=belong[y];
                add(belong[x],belong[y],1);
                add(belong[y],belong[x],0);
            }
        }
    }
    int S,q[MAXN],tail,dis_to[MAXN],dis_from[MAXN];
    void spfa1()
    {
        memset(dis_from,-1,sizeof(dis_from));
        dis_from[S]=0;
        q[1]=S;
        top=tail=1;
        in[S]=1;
        while(top<=tail)
        {
            int x=q[top++];
            in[x]=0;
            for(int i=head[x];i;i=c[i].next)
            if(c[i].w==0)
            {
               if(dis_from[x]+sum[c[i].to]>dis_from[c[i].to])
               {
                   dis_from[c[i].to]=dis_from[x]+sum[c[i].to];
                   if(!in[c[i].to])
                    in[c[i].to]=1,q[++tail]=c[i].to;
               }
            }
        }
    }
    void spfa2()
    {
        memset(dis_to,-1,sizeof(dis_to));
        q[1]=S;
        top=tail=1;
        dis_to[S]=sum[S];
        in[S]=1;
        while(top<=tail)
        {
            int x=q[top++];
            in[x]=0;
            for(int i=head[x];i;i=c[i].next)
            if(c[i].w)
            {
               if(dis_to[x]+sum[c[i].to]>dis_to[c[i].to])
               {
                   dis_to[c[i].to]=dis_to[x]+sum[c[i].to];
                   if(!in[c[i].to])
                    in[c[i].to]=1,q[++tail]=c[i].to;
               }
            }
        }
    }
    inline void Init()
    {
        n=read(),m=read();
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            Add(x,y);
        }
        for(int i=1;i<=n;i++)
         if(!dfn[i])
           Tarjan(i);
        buildnew();
        S=belong[1];
        spfa1();
        spfa2();
    }
    int ans;
    inline void work()
    {
        ans=sum[S];
        for(int i=1;i<=sz;i++)
        {
            int x=e[i].y,y=e[i].x;
            if(dis_to[x]==-1||dis_from[y]==-1)continue;
            ans=Max(ans,dis_to[x]+dis_from[y]);
        }
        printf("%d",ans);
    }
    int main()
    {
        Init();
        work();
        return 0;
    }
  • 相关阅读:
    移动视频开发让我们把会议室装进口袋里
    音视频 开发技术,让智能家居更智能!
    视频对讲SDK 大厅好友解决方案
    视频开发的安全保障措施
    手机视频开发即时通讯软件
    借音视频开发技术,开发招聘新途径
    移动视频技术的先驱
    tf.variable_scope
    sklearn 数据预处理
    Tensorflow自编码器及多层感知机
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7161898.html
Copyright © 2011-2022 走看看