最大流(模板)

来源:互联网 发布:mvc权限管理系统源码 编辑:程序博客网 时间:2024/06/07 01:06

最大流就是建一个反向边,所以说正向边加反向边之和就等于你一开始输入的值,然后找一条增广路,找出最小的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;} 
1 0
原创粉丝点击