BZOJ 1797 网络流的可行边&必须边

求完网络流以后 tarjan一发 判一判

//By SiriusRen
#include <queue>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 122222
int n,m,s,t;
struct Node{int x,y,w,r;}node[N];
struct Dinic{
    int first[N],next[N],v[N],w[N],tot,vis[10050];
    int low[N],dfn[N],in[N],stk[N],cnt,top,T,jy,p[N];
    void init(){memset(first,-1,sizeof(first));}
    void add(int x,int y,int z){Add(x,y,z),Add(y,x,0);}
    void Add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    bool tell(){
        queue<int>q;q.push(s);
        memset(vis,-1,sizeof(vis)),vis[s]=0;
        while(!q.empty()){
            int tp=q.front();q.pop();
            for(int i=first[tp];~i;i=next[i])
                if(vis[v[i]]==-1&&w[i])
                    vis[v[i]]=vis[tp]+1,q.push(v[i]);
        }
        return vis[t]!=-1;
    }
    int zeng(int x,int y){
        if(x==t)return y;
        int r=0;
        for(int i=first[x];~i&&y>r;i=next[i])
            if(vis[v[i]]==vis[x]+1&&w[i]){
                int t=zeng(v[i],min(y-r,w[i]));
                w[i]-=t,w[i^1]+=t,r+=t;
            }
        if(!r)vis[x]=-1;
        return r;
    }
    void flow(){while(tell())while(zeng(s,0x3fffffff));}
    void tarjan(int x){
        dfn[x]=low[x]=++cnt,in[x]=1,stk[++top]=x;
        for(int i=first[x];~i;i=next[i])
            if(w[i]){
                if(!dfn[v[i]])tarjan(v[i]),low[x]=min(low[x],low[v[i]]);
                else if(in[v[i]])low[x]=min(low[x],dfn[v[i]]);
            }
        if(low[x]==dfn[x]){T++;do{jy=stk[top--],p[jy]=T,in[jy]=0;}while(jy!=x);}
    }
    void solve(){
        flow();
        for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=m;i++){
            if(!w[i*2-2]&&p[node[i].x]==p[s]&&p[node[i].y]==p[t])node[i].w=2;
            else if(p[node[i].x]!=p[node[i].y]&&!w[i*2-2])node[i].w=1;
            else node[i].w=0;
        }
        for(int i=1;i<=m;i++){
            if(node[i].w==2)puts("1 1");
            else if(node[i].w==1)puts("1 0");
            else puts("0 0");
        }
    }
}dinic;
int main(){
    dinic.init();
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].w);
        dinic.add(node[i].x,node[i].y,node[i].w);
    }
    dinic.solve();
}

这里写图片描述

原文地址:https://www.cnblogs.com/SiriusRen/p/6532129.html