zoukankan      html  css  js  c++  java
  • 最大流(模板)

    最大流就是建一个反向边,所以说正向边加反向边之和就等于你一开始输入的值,然后找一条增广路,找出最小的cos,把最大流tot加上cos,然后正向边减cos,反向边加cos,这样可以修正错误,因为其实你不用这样流,可你这样流了,就这样直到找不到增广路,就找不到更多的流量了,这时的值就是最大的,其实就是一次一次添流量,直到不能添了
    1.EK(Edmond—Karp)算法
    也就是广搜版

    #include<cstdio>
    #include<iostream>
    #include<cstring> 
    using namespace std;
    const int M=1999999,INF=999999999;
    int n,m,s,t,used[M];
    int f[10999][10999];
    int a[M],pre[M];int d[M];
    int bfs(int s,int t){
        int flow=0;
    
        while(1){
            memset(a,0,sizeof(a));
            memset(d,0,sizeof(d));
            a[s]=INF;
    
            int h=0,tail=1;
            d[1]=s;
            while(h<tail){
            h++;
            int x=d[h];
            for(int i=1;i<=n;i++)
            if(f[x][i]&&!a[i])
            {
                pre[i]=x;
                a[i]=min(a[x],f[x][i]);
                d[++tail]=i;
            }
            }
            if(!a[t]) break;
            for(int i=t;i!=s;i=pre[i])
            {
                f[pre[i]][i]-=a[t];
                f[i][pre[i]]+=a[t];
            }
            flow+=a[t];
    
    
        }
    
        return flow;
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1;i<=m;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            f[x][y]+=z;
        }
        int d=bfs(s,t);
        printf("%d",d);
        return 0;
    } 

    2.Ford-Fulkerson算法
    也就是深搜版
    这里用的链表
    位运算是为了找反向边

    #include<cstdio>
    #include<iostream>
    #include<cstring> 
    using namespace std;
    const int M=199999,INF=999999999;
    int n,m,s,t,used[M];
    int nex[M],head[M],cos[M],to[M],tot;
    int add(int x,int y,int z){
        cos[tot]=z;
        nex[++tot]=head[x];
        to[tot]=y;
        head[x]=tot;
    }
    int dfs(int s,int t,int f){
        if(s==t) return f;
        for(int i=head[s];i;i=nex[i]){
            int tmp=to[i];
            if(cos[i-1]&&!used[tmp]){
                used[tmp]=1;
                int d=dfs(tmp,t,min(cos[i-1],f));
                if(d>0){
                    cos[i-1]-=d;
                    cos[(i-1)^1]+=d;
                    return d;
                }
            }
        }   
    }
    int maxflow(int s,int t){
        int flow=0;
        while(1){
            memset(used,0,sizeof(used));
            int d=dfs(s,t,INF);
            if(d==0)return flow;
            flow+=d;
        }
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1;i<=m;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,0);
        }
        int d=maxflow(s,t);
        printf("%d",d);
        return 0;
    } 

    3.还有Dinic算法
    就是综合以上两种方法,先用bfs建一个有层次的图,同一个层次的一定不是增广路,再用dfs找减少多余同层次的,就比较省事

    #include<cstdio>
    #include<iostream>
    #include<cstring> 
    #include<queue>
    using namespace std;
    const int M=199999,INF=999999999;
    int n,m,s,t,used[M],deep[M];
    int nex[M],head[M],cos[M],to[M],tot;
    int add(int x,int y,int z){
        cos[tot]=z;
        nex[++tot]=head[x];
        to[tot]=y;
        head[x]=tot;
    }
    int bfs(int s,int t){
        queue< int > d; 
        memset(deep,-1,sizeof(deep));
        deep[s]=0;
        d.push(s);
        while(!d.empty()){
            int x=d.front();
            d.pop();
            for(int i=head[x];i;i=nex[i]){
                int tmp=to[i];
                if(cos[i-1]&&deep[tmp]==-1){
                    deep[tmp]=deep[x]+1;
                    d.push(tmp);
                }
            }   
        }
        return deep[t]!=-1; 
    } 
    int dfs(int s,int t,int f){
        if(s==t) return f;
        for(int i=head[s];i;i=nex[i]){
            int tmp=to[i];
            if(cos[i-1]&&deep[s]+1==deep[tmp]){
                int d=dfs(tmp,t,min(cos[i-1],f));
                if(d>0){
                    cos[i-1]-=d;
                    cos[(i-1)^1]+=d;
                    return d;
                }
            }
        }   
    }
    int maxflow(int s,int t){
        int flow=0;
        while(bfs(s,t)){
            while(1)
            {
                int d=dfs(s,t,INF);
            if(d==0)break;
            flow+=d;
            }
    
        }
        return flow;
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1;i<=m;i++){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,0);
        }
        int d=maxflow(s,t);
        printf("%d",d);
        return 0;
    } 
  • 相关阅读:
    Android开发环境搭建&第一个Android工程建立
    Pytest学习笔记8参数化
    Pytest学习笔记3fixture
    Pytest学习笔记2setup和teardown
    Pytest学习笔记1快速入门
    Pytest学习笔记4assert断言
    Pytest学习笔记9失败重跑
    Pipenv虚拟环境
    Pytest学习笔记7skip和skipif的使用
    Pytest学习笔记6自定义标记mark
  • 原文地址:https://www.cnblogs.com/wspl98765/p/6819870.html
Copyright © 2011-2022 走看看