【BZOJ1797】Minimum Cut (AHOI2009)-Minimum Cut+SCC

Test address: Minimum cut
method: This question requires the use of minimum cut + SCC.
First of all, according to the relationship between the maximum flow and the minimum cut, it is not difficult to see that the edges without full flow after running the maximum flow cannot appear in the minimum cut.
Then for the remaining edge, if its two endpoints are in the residual network (note that the residual network has reverse edges) in the same strongly connected component, it is obviously impossible to appear in the minimum cut (because It doesn't make sense to cut this edge), otherwise it might appear in a minimal cut.
And for an edge, if its two endpoints are in the same strongly connected component as the source and sink respectively in the residual network, then it must appear in the minimum cut, because once its capacity becomes larger, we can Augment a new maximum flow, contradictory.
After drawing the above conclusions, we can determine which case each edge belongs to according to the above conditions.
Here is my code:

#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\n");continue;}
        if (belong[e[i<<1].v]!=belong[e[i<<1|1].v]) printf("1 ");
        else {printf("0 0\n");continue;}
        if (belong[e[i<<1].v]==belong[T]&&belong[e[i<<1|1].v]==belong[S])
            printf("1\n");
        else printf("0\n");
    }

    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324909712&siteId=291194637
cut