• ISAP网络流


    ISAP是的dicnic基础上优化得到的一直最大流算法,其包含了当前弧优化和分层图优化,且分层图无需重新构建,会在运行过程中处理。

    ISAP 的终止条件为出现断层div。
    对于层数 > div 的点,满流。
    反之,则未满流。

    在最大全闭合图问题中,答案为满流的点的组合。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int _ = 2e4+10;
    const int N = 410,inf=0x3f3f3f3f;
    
    void in(int &x){
        x=0;int y = 1;
        char c=getchar();
        while(!isdigit(c)){if(c=='-')y=-1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
        x*=y;
    }
    void o(int x){
        printf("%lld",x);
    }
    
    int n,m;
    //前向星村边,注意始边从2开始,而不再是1。
    struct {int v,nxt,f;}e[_];int cnt = 1;
    struct ISAP{
    //规定起点和重点,一般为n+1,和n+2
        int S = 0,T=0;
    //    head 前线星头部,初始化为0
        int head[N]={0};
    //    d 当前弧线 gap 各层点的数量 h 点的高度
        int h[N],gap[N],d[N];
        void add(int u,int v,int f){
    //       正边,反边。
            e[++cnt]={v,head[u],f};head[u]=cnt;
            swap(u,v);
            e[++cnt]={v,head[u],0};head[u]=cnt;
        }
        int sap(int u,int flow){
    //        流至T,退出
            if(u==T)return flow;
    //        流量
            int rec=0;
    //        从当前弧搜索可行流
            for(int i=d[u];i;i=e[i].nxt){
                if(h[u]==h[e[i].v]+1&&e[i].f){
    //              流量 ret
                    int ret = sap(e[i].v,min(flow-rec,e[i].f));
    //              正流+,反流减小并且记录当前弧
                    e[i].f-=ret;e[i^1].f+=ret;d[u]=i;
    //               达到可行最大流即使终止,
                    if((rec+=ret)==flow)return flow;
                }
            }
    //        当前层数点数-1,若出现断层则已经找到最大流
            if(!(--gap[h[u]]))h[S]=T;
    //        下一层++,当前弧线还原
            gap[++h[u]]++;d[u]=head[u];
            return rec;
        }
        void init(){
            S=n+1,T=n+2;
            for(int i=1;i<=T;i++)head[i]=d[i]=0,h[i]=gap[i]=0;
        }
        int cal(){
            for(int u=0,v=0,i=1;;i++){
                in(u);in(v);
                if(u==-1)break;
                add(u,v,1);
            }
            for(int i=1;i<=m;i++)add(S,i,1);
            for(int i=m+1;i<=n;i++)add(i,T,1);
            int maxflow;
            gap[maxflow=0]=T;
            for(int i=1;i<=T;i++)d[i]=head[i];
            while(h[S]<T)maxflow+=sap(S,inf);
            return maxflow;
        }
        void printedge(){
            for(int i=1;i<=n;i++){
                for(int j=head[i];j;j=e[j].nxt){
                    if(j%2==0&&e[j].f==0&&e[j].v!=S&&e[j].v!=T){
                        o(i);putchar(' ');o(e[j].v);putchar('
    ');
                    }
                }
            }
        }
    }MAXF;
    
    signed main(){
    //    in(n);in(m);
        in(m);in(n);
        
        o(MAXF.cal());putchar('
    ');
        MAXF.printedge();
        return 0;
    }
    
  • 相关阅读:
    js中的投掷筛子的小游戏
    js俩习题
    python中socket理论
    python实现计时器(装饰器)
    python之正则表达式(re模块)用法总结
    python练习题之随机生成验证码
    python中模块介绍
    python中的装饰器基本理论
    python类与对象练习题扑克牌
    Java抓取网页数据
  • 原文地址:https://www.cnblogs.com/yesuweiYYYY/p/15508240.html
Copyright © 2020-2023  润新知