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;
    }
  • 相关阅读:
    English 2
    速算24点
    心理学1
    从微服务到函数式编程
    034 01 Android 零基础入门 01 Java基础语法 04 Java流程控制之选择结构 01 流程控制概述
    033 01 Android 零基础入门 01 Java基础语法 03 Java运算符 13 运算符和表达式知识点总结
    032 01 Android 零基础入门 01 Java基础语法 03 Java运算符 12 运算符和if-else条件语句的综合案例——闰年问题
    031 01 Android 零基础入门 01 Java基础语法 03 Java运算符 11 运算符的优先级
    030 01 Android 零基础入门 01 Java基础语法 03 Java运算符 10 条件运算符
    029 01 Android 零基础入门 01 Java基础语法 03 Java运算符 09 逻辑“非”运算符
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7161898.html
Copyright © 2011-2022 走看看