BZOJ1797 AHOI2009 Mincut最小割 网络流+连通性

题意:给定一张图,求每一条边:1、是否在一个最小割的方案里  2、是否在每一个最小割的方案里

题解:

先做最小割,然后在残余网络上缩点。对于一条边(u,v)

如果f[u]!=f[v],则(u,v)可以在某个最小割上(缩点后的图上的边均为满流边)

如果f[u]==f[S] && f[v]==f[T],则(u,v)在所有的最小割上(增大c(u,v)会导致最小割增大)

#include <stack>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=40000+2;
const int MAXM=600000+2;
struct EDGE{
    int v,u,c;
    EDGE(){}
    EDGE(int _v,int _u,int _c):v(_v),u(_u),c(_c){}
}e[2*MAXM];
int N,M,S,T,cnt,d[MAXN],f[MAXN],cur[MAXN],dfn[MAXN],low[MAXN],scc,depth;
bool ans1[MAXN],ans2[MAXN],flag[MAXN];
queue<int> q;
stack<int> s;
vector<int> tab[MAXN];

void Insert(int u,int v,int c){
    tab[u].push_back(cnt),e[cnt++]=EDGE(u,v,c);
    tab[v].push_back(cnt),e[cnt++]=EDGE(v,u,0);
}

bool BFS(int s,int t){
    memset(d,-1,sizeof(d));
    d[s]=0,q.push(s);

    int x;
    while(!q.empty()){
        x=q.front(),q.pop();
        for(int i=0;i<tab[x].size();i++)
            if(d[e[tab[x][i]].u]==-1 && e[tab[x][i]].c)
                d[e[tab[x][i]].u]=d[x]+1,q.push(e[tab[x][i]].u);
    }
    return d[t]>0;
}

int DFS(int x,int f,int t){
    if(x==t) return f;

    int flow,used=0;
    for(int i=cur[x];i<tab[x].size();i++)
        if(e[tab[x][i]].c && d[e[tab[x][i]].u]==d[x]+1){
            flow=DFS(e[tab[x][i]].u,min(f-used,e[tab[x][i]].c),t);
            e[tab[x][i]].c-=flow,e[tab[x][i]^1].c+=flow,used+=flow;
            if(e[tab[x][i]].c) cur[x]=i;
            if(f==used) return f;
        }

    if(!used) d[x]=-1;
    return used;
}

void Dinic(int s,int t){
    while(BFS(s,t)){
        memset(cur,0,sizeof(cur));
        DFS(s,INT_MAX,t);
    }
}

void Tarjan(int x){
    dfn[x]=low[x]=++depth,flag[x]=1,s.push(x);
    for(int i=0;i<tab[x].size();i++){
        if(!e[tab[x][i]].c) continue;
        if(!dfn[e[tab[x][i]].u]) Tarjan(e[tab[x][i]].u),low[x]=min(low[x],low[e[tab[x][i]].u]);
        else if(flag[e[tab[x][i]].u]) low[x]=min(low[x],dfn[e[tab[x][i]].u]);
    }

    if(low[x]==dfn[x]){
        int t=-1;scc++;
        while(t!=x){
            t=s.top(),s.pop(),flag[t]=0;
            f[t]=scc;
        }
    }
}

int main(){
    scanf("%d %d %d %d",&N,&M,&S,&T);
    for(int i=1,u,v,c;i<=M;i++){
        scanf("%d %d %d",&u,&v,&c);
        Insert(u,v,c);
    }

    Dinic(S,T);
    for(int i=1;i<=N;i++)
        if(!dfn[i]) Tarjan(i);

    for(int i=0;i<cnt;i+=2){
        if(e[i].c) puts("0 0");
        else{
            if(f[e[i].v]!=f[e[i].u]) printf("1 ");
            else printf("0 ");
            if(f[e[i].v]==f[S] && f[e[i].u]==f[T]) printf("1\n");
            else printf("0\n");
        }
    }

    return 0;
}
View Code

 

posted @ 2017-02-28 22:31  WDZRMPCBIT  阅读(154)  评论(0编辑  收藏  举报