zoukankan      html  css  js  c++  java
  • 网络流——ISAP

    我数次想要写网络流的博客,但是东西太多了,我又太颓了,以至于一直没有写……

    这次就写一个ISAP吧!学了ISAP和(自己的)Dinic一比,感觉还是快了许多的!(不是和loj上前几名的大佬的Dinic比)

    最大流还有一点要吐槽的,就是当前弧优化不知道为什么写不对(每次加过之后Dinic就会变慢……),所以一直就没加当前弧优化……

    由于本人太懒了,不想写一遍思路,具体请参见注释。

    注:代码注释中"和Dinic相同"之类的字眼,不用担心,我之后会加一篇Dinic的博客。

    #include<cstdio>
    #include<cstring>
    #define min(a,b) (a<b?a:b)
    #define MXN 10000+2
    #define MXM 100000+10
    int v[2*MXM],flow[2*MXM],fst[MXN],nxt[2*MXM];   //----邻接表 
    int layer[MXN],gap[MXN];               //----网络图信息:layer-层、gap-优化数组 
    int etop,S,T,n;                //----etop边数,S源点,T汇点,n点数 
    int queue[MXN+100],head,tail;//----手打队列 
    void AddEdge(int x,int y,int z){
        //----加边函数:每次连续加正反两条边
        //----从0开始加边,可以用位运算瞎搞,第i条边的反向边为第i^1条边 
        v[etop]=y;
        flow[etop]=z;
        nxt[etop]=fst[x];
        fst[x]=etop++;
        v[etop]=x;
        flow[etop]=0;
        nxt[etop]=fst[y];
        fst[y]=etop++;
        return;
    }
    void GraphInit(){
        //----建图(残量网络) 
        memset(fst,-1,sizeof(fst));
        memset(nxt,-1,sizeof(nxt));
        int m,x,y,z;
        scanf("%d%d%d%d",&n,&m,&S,&T);
        etop=0;
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&x,&y,&z);
            AddEdge(x,y,z);
        }
        return;
    }
    void ISAPInit(){
        //----ISAP初始化,上来从汇点bfs分一下层,用于之后dfs
        //----同时加gap优化 
        memset(layer,-1,sizeof(layer));
        memset(gap,0,sizeof(gap));
        queue[tail++]=T;
        layer[T]=0;
        gap[layer[T]]++;
        while(head<tail){
            int x=queue[head++];
            for(int y=fst[x];y!=-1;y=nxt[y]){
                if(layer[v[y]]==-1){
                    layer[v[y]]=layer[x]+1;
                    gap[layer[v[y]]]++;
                    queue[tail++]=v[y];
                }
            }
        }
        return;
    }
    int ISAPDfs(int now,int f){
        //----ISAP求解最大流的主要函数
        //----Dfs到汇点直接返回
        if(now==T) return f;
        int sum=0,temp;
        for(int y=fst[now];y!=-1;y=nxt[y]){
            //----和Dinic的Dfs相同
            if(layer[v[y]]+1==layer[now]){
                temp=ISAPDfs(v[y],min(flow[y],f));
                sum+=temp;
                f-=temp;
                flow[y]-=temp;
                flow[y^1]+=temp;
                if(f==0) return sum;
            }
        }
        //----gap优化的核心,也算是ISAP很快的主要原因
        //----gap记录每一层的点数 
        if(--gap[layer[now]]==0) layer[S]=n;
        ++gap[++layer[now]];
        //----首先,这次Dfs后,这一个点满足分层条件的所有边都已经增广
        //----因此这个点已经不用在这一层待着了,但是由于我们不知道他可以到哪一层,将层数++,下次Dfs再试
        //----同时将原层数的gap--。优化在于,如果减后gap==0,那么就会出现断层,之后就没有满足分层的增广路了
        //----就可以不用ISAP了,就将S的layer置为n 
        return sum;
    }
    int ISAP(){
        int ans=0;
        ISAPInit();
        while(layer[S]<n) ans+=ISAPDfs(S,0x7fffffff);
        //----S的层是n的话,表示一定出现了断层,或者已经没有从S出发的增广路了(即进行过layer[S]++)
        //----因此不能再增广了,一定达到了最大流,退出ISAP即可。 
        return ans;
    }
    int main(){
        GraphInit();
        printf("%d",ISAP());
        return 0;
    }
    ISAP

    代码交到洛谷模板题上可AC。

  • 相关阅读:
    Vue Scroller:Vue 下拉刷新及无限加载组件
    vue引用公用的头部和尾部文件。
    Java后期拓展(三)Nginx ——高性能的HTTP和反向代理服务器
    JAVA后期拓展(二)ZooKeeper——分布式应用程序协调服务系统
    Java高级部分
    Java后期拓展(一)非关系型数据库Redis
    LoadRunner(四)——深度了解LR相关功能
    LoadRunner(三)——LR相关概念&组成部分
    LoadRunner(二)——性能测试过程概述
    LoadRunner(一)——性能测试基础及性能指标概述
  • 原文地址:https://www.cnblogs.com/halifuda/p/8403723.html
Copyright © 2011-2022 走看看