其他分享
首页 > 其他分享> > P4126 [AHOI2009]最小割(网络流+tarjan)

P4126 [AHOI2009]最小割(网络流+tarjan)

作者:互联网

P4126 [AHOI2009]最小割

边$(x,y)$是可行流的条件:

1.满流;2.残量网络中$x,y$不连通

边$(x,y)$是必须流的条件:

1.满流;2.残量网络中$x,S$与$y,T$分别连通

现在的问题是怎么判断点之间是否连通

我们可以在残量网络上跑tarjan,处理出强连通分量

如果两点同属一个强连通分量,那么它们之间就连通辣

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define N 10005
#define M 1000005
int n,m,S,T,d[N],cur[N];
queue <int> h; bool vis[N];
int Clock,tp,st[N],dfn[N],low[N],be[N],bel;
int cnt=1,hd[N],nxt[M],ed[N],poi[M],val[M],fr[M];
inline void adde(int x,int y,int v){
    nxt[ed[x]]=++cnt, hd[x]=hd[x]?hd[x]:cnt,
    ed[x]=cnt, poi[cnt]=y, val[cnt]=v, fr[cnt]=x;
}
inline void link(int x,int y,int v){adde(x,y,v),adde(y,x,0);}
bool bfs(){
    memset(vis,0,sizeof(vis));
    h.push(S); vis[S]=1;
    while(!h.empty()){
        int x=h.front(); h.pop();
        for(int i=hd[x];i;i=nxt[i]){
            int to=poi[i];
            if(!vis[to]&&val[i]>0)
                d[to]=d[x]+1,vis[to]=1,h.push(to);
        }
    }return vis[T];
}
int dfs(int x,int a){
    if(x==T||a==0) return a;
    int F=0,f;
    for(int &i=cur[x];i;i=nxt[i]){
        int to=poi[i];
        if(d[to]==d[x]+1&&(f=dfs(to,min(a,val[i])))>0)
            a-=f,F+=f,val[i]-=f,val[i^1]+=f;
        if(!a) break;
    }return F;
}
int dinic(){
    int re=0;
    while(bfs()){
        for(int i=1;i<=n;++i) cur[i]=hd[i];
        re+=dfs(S,2e9);
    }return re;
}
void tarjan(int x){//板子
    dfn[x]=low[x]=++Clock; st[++tp]=x;
    for(int i=hd[x];i;i=nxt[i]){
        if(!val[i]) continue;//满流的不跑
        int to=poi[i];
        if(!dfn[to]) tarjan(to),low[x]=min(low[x],low[to]);
        else if(!be[to]) low[x]=min(low[x],dfn[to]);
    }
    if(dfn[x]==low[x]){
        be[x]=++bel;
        while(st[tp]!=x) be[st[tp--]]=bel;
        --tp;
    }
}
int main(){
    scanf("%d%d%d%d",&n,&m,&S,&T);
    for(int i=1,u,v,w;i<=m;++i)
        scanf("%d%d%d",&u,&v,&w),link(u,v,w);
    int tmp=dinic();
    for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
    for(int i=2;i<=cnt;i+=2){
        printf((!val[i]&&be[fr[i]]!=be[poi[i]])?"1 ":"0 ");
        puts((!val[i]&&be[fr[i]]==be[S]&&be[poi[i]]==be[T])?"1":"0");
    }return 0;
}

 

标签:tarjan,连通,val,vis,AHOI2009,cnt,int,P4126,hd
来源: https://www.cnblogs.com/kafuuchino/p/10802132.html