• 【BZOJ1797】最小割(AHOI2009)-最小割+SCC


    测试地址:最小割
    做法:本题需要用到最小割+SCC。
    首先,根据最大流和最小割的关系不难看出,跑完最大流后没有满流的边都不可能出现在最小割中。
    那么对于剩下的边,如果它的两个端点在残余网络中(注意,残余网络是带反向边的)在同一个强连通分量内,很显然它也不可能出现在最小割中(因为割掉这条边没什么意义),否则它就可能出现在最小割中。
    而对于一条边,如果它的两个端点在残余网络中分别和源点和汇点在同一个强连通分量中,那么它就一定出现在最小割中,因为一旦它容量变大,我们就可以增广出新的最大流,矛盾。
    得出上述的结论之后,我们就可以按照上面的条件判定每条边属于哪种情况了。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll inf=(ll)1000000000*(ll)1000000000;
    int n,m,S,T,first[4010]={0},tot=1;
    int lvl[4010],cur[4010],h,t,q[4010];
    int st[4010],belong[4010],top=0,totscc=0,dfn[4010],low[4010],tim=0;
    bool vis[4010]={0},inst[4010]={0};
    struct edge
    {
        int v,next;
        ll f;
    }e[120010];
    
    void insert(int a,int b,ll f)
    {
        e[++tot].v=b,e[tot].next=first[a],e[tot].f=f,first[a]=tot;
        e[++tot].v=a,e[tot].next=first[b],e[tot].f=0,first[b]=tot;
    }
    
    bool makelevel()
    {
        for(int i=1;i<=n;i++)
            lvl[i]=-1,cur[i]=first[i];
        h=t=1;
        q[1]=S;
        lvl[S]=0;
        while(h<=t)
        {
            int v=q[h++];
            for(int i=first[v];i;i=e[i].next)
                if (e[i].f&&lvl[e[i].v]==-1)
                {
                    lvl[e[i].v]=lvl[v]+1;
                    q[++t]=e[i].v;
                }
        }
        return lvl[T]!=-1;
    }
    
    ll maxflow(int v,ll maxf)
    {
        ll ret=0,f;
        if (v==T) return maxf;
        for(int i=cur[v];i;i=e[i].next)
        {
            if (e[i].f&&lvl[e[i].v]==lvl[v]+1)
            {
                f=maxflow(e[i].v,min(maxf-ret,e[i].f));
                ret+=f;
                e[i].f-=f;
                e[i^1].f+=f;
                if (ret==maxf) break;
            }
            cur[v]=i;
        }
        if (!ret) lvl[v]=-1;
        return ret;
    }
    
    void dinic()
    {
        while(makelevel()) maxflow(S,inf);
    }
    
    void tarjan(int v)
    {
        vis[v]=inst[v]=1;
        st[++top]=v;
        dfn[v]=low[v]=++tim;
        int now=top;
        for(int i=first[v];i;i=e[i].next)
            if (e[i].f)
            {
                if (!vis[e[i].v])
                {
                    tarjan(e[i].v);
                    low[v]=min(low[v],low[e[i].v]);
                }
                else if (inst[e[i].v]) low[v]=min(low[v],dfn[e[i].v]);
            }
        if (dfn[v]==low[v])
        {
            totscc++;
            for(int i=now;i<=top;i++)
            {
                belong[st[i]]=totscc;
                inst[st[i]]=0;
            }
            top=now-1;
        }
    }
    
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&S,&T);
        for(int i=1;i<=m;i++)
        {
            int a,b;
            ll c;
            scanf("%d%d%lld",&a,&b,&c);
            insert(a,b,c);
        }
    
        dinic();
        for(int i=1;i<=n;i++)
            if (!vis[i]) tarjan(i);
        for(int i=1;i<=m;i++)
        {
            if (e[i<<1].f) {printf("0 0
    ");continue;}
            if (belong[e[i<<1].v]!=belong[e[i<<1|1].v]) printf("1 ");
            else {printf("0 0
    ");continue;}
            if (belong[e[i<<1].v]==belong[T]&&belong[e[i<<1|1].v]==belong[S])
                printf("1
    ");
            else printf("0
    ");
        }
    
        return 0;
    }
  • 相关阅读:
    场曲——像差相关
    曲面探测器相关——查资料
    光学系统联合设计
    Python3:Django连接Mysql数据库时出错,'Did you install mysqlclient or MySQL-python?'
    Python3.x:pip install pymssql安装时出错
    Python3:自动发送账单邮件
    Python3:input()输入函数的用法
    Python3:读取配置dbconfig.ini(含有中文)显示乱码的解决方法
    python3:利用smtplib库和smtp.qq.com邮件服务器发送邮件
    CSS3:布局display属性的flex(弹性布局)
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793436.html
Copyright © 2020-2023  润新知