BZOJ 1797最小割

3375 ワード

タイトルリンク:http://61.187.179.132/JudgeOnline/problem.php?id=1797
題意:有向図を与え、各辺に流量があり、ソースポイントの合流点s、tを与える.各エッジについて、(1)最小分割がそのエッジを含むかどうかを尋ねます.(2)すべての最小カットにそのエッジが含まれていますか?
構想:まず最大ストリームを求め、残りのネットワークの中で強い連通成分を求める.各原図中のエッジ(最大ストリームに追加された逆エッジは計算されない)について、エッジの残留流量が0であり、uとvが2つの異なる強い連通成分にある場合、最小分割がエッジを含む.上記で満たされ、uとsは、1つの連通成分、vとtが1つの連通成分である場合に、すべての最小分割がこのエッジを含む.
 
struct node

{

    int u,v,cap,id,next;

};





node edges[N*50];

int head[N],e;





int pre[N],num[N],h[N],cur[N];

int s,t;





int Maxflow(int s,int t,int n)

{

    int i;

    for(i=0;i<n;i++) cur[i]=head[i];

    int u=s,Min,k,v,ans=0;

    while(h[u]<n)

    {

        if(u==t)

        {

            Min=INF;

            for(i=s;i!=t;i=edges[cur[i]].v)

            {

                k=cur[i];

                if(edges[k].cap<Min) Min=edges[k].cap,v=i;

            }

            ans+=Min; u=v;

            for(i=s;i!=t;i=edges[cur[i]].v)

            {

                k=cur[i];

                edges[k].cap-=Min;

                edges[k^1].cap+=Min;

            }

        }

        for(i=cur[u];i!=-1;i=edges[i].next)

        {

            if(edges[i].cap>0&&h[u]==h[edges[i].v]+1) break;

        }

        if(i!=-1)

        {

            cur[u]=i;

            pre[edges[i].v]=u;

            u=edges[i].v;

        }

        else

        {

            if(--num[h[u]]==0) break;

            cur[u]=head[u];

            Min=n;

            for(i=head[u];i!=-1;i=edges[i].next)

            {

                if(edges[i].cap>0&&h[edges[i].v]<Min) Min=h[edges[i].v];

            }

            h[u]=Min+1;

            num[Min+1]++;

            if(u!=s) u=pre[u];

        }

    }

    return ans;

}





int n,m;





void add(int u,int v,int w,int id)

{

    edges[e].u=u;

    edges[e].v=v;

    edges[e].cap=w;

    edges[e].id=id;

    edges[e].next=head[u];

    head[u]=e++;

}









int dfn[N],low[N],id,Num,color[N],visit[N];

stack<int> S;





void DFS(int u)

{

    low[u]=dfn[u]=++id;

    S.push(u);

    

    int i,v;

    for(i=head[u];i!=-1;i=edges[i].next) 

    {

        v=edges[i].v;

        if(edges[i].cap<=0) continue;

        if(!dfn[v])

        {

            DFS(v);

            low[u]=min(low[u],low[v]);

        }

        else if(!visit[v])

        {

            low[u]=min(low[u],dfn[v]);

        }

    }

    if(low[u]==dfn[u])

    {

        Num++;

        do

        {

            v=S.top();

            S.pop();

            visit[v]=1;

            color[v]=Num;

        }while(v!=u);

    }

}





int ans[N*30][2];





int main()

{

    clr(head,-1);

    RD(n,m); RD(s,t);

    int u,v,w,i;

    FOR1(i,m) 

    {

        RD(u,v,w);

        add(u,v,w,i);

        add(v,u,0,0);

    }

    Maxflow(s,t,n+1);

    FOR1(i,n) if(!visit[i]) DFS(i);

    FOR0(i,e)

    {

        u=edges[i].u;

        v=edges[i].v;

        w=edges[i].id;

        if(color[u]==color[v]) continue;

        if(edges[i].cap>0) continue;

        ans[w][0]=1;

        if(color[u]==color[s]&&color[v]==color[t]) 

        {

            ans[w][1]=1;

        }

    }

    FOR1(i,m) PR(ans[i][0],ans[i][1]);

}