• 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;
    }
  • 相关阅读:
    ansible
    爬虫框架之scrapy
    Mongodb
    xml 创建 添加节点或属性(自定义,复制)
    web站点崩溃的原因总结
    C# 关闭正在执行的文件
    254. Factor Combinations
    256. Paint House
    156. Binary Tree Upside Down
    170. Two Sum III
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10802132.html
Copyright © 2020-2023  润新知