[BZOJ1797][Ahoi2009]Mincut 最小割:最小割+Tarjan

分析:

最小割可行边必需边模板题。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>

inline int read(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x;
}

const int MAXN=4005;
const int MAXM=60005;
int n,m,s,t,maxflow,mincut,ecnt=-1,head[MAXN];
int dfn[MAXN],low[MAXN],tot,Stack[MAXN],Top,id[MAXN],tot2;
int dep[MAXN],cur[MAXN];
bool In[MAXN];
std::queue<int> q;
struct Edge{
    int to,nxt,cap,fr;
}e[MAXM<<1];
struct Edge2{
    int u,v;
}ee[MAXM];

inline void add_edge(int bg,int ed,int ca){
    ecnt++;
    e[ecnt].to=ed;
    e[ecnt].nxt=head[bg];
    e[ecnt].cap=ca;
    e[ecnt].fr=bg;
    head[bg]=ecnt;
}

inline bool bfs(){
    memset(dep,0x3f,sizeof dep);
    for(int i=1;i<=n;i++) cur[i]=head[i];
    while(!q.empty()) q.pop();
    dep[s]=1;
    q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i!=-1;i=e[i].nxt){
            int ver=e[i].to;
            if(dep[ver]>1e9&&e[i].cap){
                dep[ver]=dep[u]+1;
                q.push(ver);
            }
        }
    }
    return dep[t]<1e9;
}

int dfs(int x,int pref){
    if(x==t||!pref) return pref;
    int flow=0,temp;
    for(int& i=cur[x];i!=-1;i=e[i].nxt){
        int ver=e[i].to;
        if(dep[ver]==dep[x]+1&&(temp=dfs(ver,std::min(pref,e[i].cap)))){
            e[i].cap-=temp;
            e[i^1].cap+=temp;
            pref-=temp;
            flow+=temp;
            if(!pref) break;
        }
    }
    return flow;
}

inline void dinic(){
    while(bfs()) maxflow+=dfs(s,1e9);
}

void tarjan(int x){
    dfn[x]=low[x]=++tot;
    Stack[++Top]=x;
    In[x]=1;
    for(int i=head[x];i!=-1;i=e[i].nxt){
        if(!e[i].cap) continue;
        int ver=e[i].to;
        if(!dfn[ver]){
            tarjan(ver);
            low[x]=std::min(low[x],low[ver]);
        }
        else if(In[ver])
            low[x]=std::min(low[x],low[ver]);
    }
    if(low[x]==dfn[x]){
        tot2++;
        while(Stack[Top+1]!=x){
            id[Stack[Top]]=tot2;
            In[Stack[Top]]=0;
            Top--;
        }
    }
}

int main(){
    memset(head,-1,sizeof head);
    n=read(),m=read();
    s=read(),t=read();
    for(int i=1;i<=m;i++){
        int u=read(),v=read(),ca=read();
        add_edge(u,v,ca);
        add_edge(v,u,0);
        ee[i].u=u;ee[i].v=v;
    }
    dinic();
    mincut=maxflow;
    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan(i);
    for(int i=1;i<=m;i++){
        if(e[(i-1)<<1].cap) printf("0 0\n");
        else if(id[ee[i].u]==id[ee[i].v]) printf("0 0\n");
        else if(id[ee[i].u]!=id[s]||id[ee[i].v]!=id[t]) printf("1 0\n");
        else printf("1 1\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9694473.html