网络流之最大流问题-增广方法

来源:互联网 发布:天通银手机交易软件 编辑:程序博客网 时间:2024/05/18 03:35

网络流中的最大流问题求解算法有很多,这里就只介绍用增广BFS算法实现的一种:可做一般求解最大流的模板:

代码如下:


#include <iostream>#include <stdio.h>#include <string.h>#include <queue>#define INF 100000//无穷#define MAX 500//结点上限#define Min(x,y) x<y?x:yusing namespace std;int map[MAX][MAX];//网络int flow[MAX][MAX];//可行流int d[MAX];//首先做标志数组,然后做存储最大公共增量的数组。int pre[MAX];//记录结点的父节点int n,m;//n个顶点,m条边int max_flow(int s,int t)//s,起点,t,汇点{    queue <int> q;    int ans,u,v;    ans=0;    memset(flow,0,sizeof(flow));    while(1)    {        memset(d,0,sizeof(d));        memset(pre,0,sizeof(pre));        d[s]=INF;        q.push(s);        while(!q.empty())//BFS寻找增广路径        {            u=q.front();            q.pop();            for (v=1;v<=n;v++)            {                if (!d[v] && map[u][v]>flow[u][v])//如果v结点没有访问过,并且该边没有饱和                {                    pre[v]=u;//记录父结点                    q.push(v);                    d[v]=Min(d[u],map[u][v]-flow[u][v]);//从父结点的增量与当前结点的增量中选最小的                }            }        }        if (d[t]==0) break;//如果汇未被标上号,即没有这样的顶点可选时,即为最大流        for (u=t;u!=s;u=pre[u])//从汇点往源点,为可行流赋值        {            flow[pre[u]][u]+=d[t];//将公共增量加入flow            flow[u][pre[u]]-=d[t];//若为负边,则减去a【t】        }        ans+=d[t];//最大流    }    return ans;}int main(){    int i,x,y,z;    while(cin>>m>>n)    {        memset(map,0,sizeof(map));        for (i=0;i<m;i++)        {            cin>>x>>y>>z;            map[x][y]+=z;        }        int s=1,t=n;        cout<<max_flow(s,t)<<endl;    }    return 0;}
上面这个列子模板只是针对于单源单汇问题:如HDU acm上的1532.就是典型的最大网络流问题:

但是对于多源多汇的问题,其实也是一样,只是我们需要换一种思路而已。如POJ acm-1459 Power Network问题:

算法思路图示:

思路就是把多源转化为单源,多汇转化为单汇。其他一切都不变。

这是POJ 1459的代码:

#include <iostream>#include <stdio.h>#include <string.h>#include <queue>#define N 105#define INF 100000#define Min(x,y) x<y?x:yusing namespace std;int map[N][N];int flow[N][N];int a[N];int p[N];int n,np,nc,m;int max_flow(int s,int t){queue <int> q;int ans,u,v;ans=0;memset(flow,0,sizeof(flow));while(1){memset(a,0,sizeof(a));memset(p,0,sizeof(p));a[s]=INF;q.push(s);while(!q.empty()){u=q.front();q.pop();for (v=0;v<=n+1;v++){if (!a[v] && map[u][v]>flow[u][v]){p[v]=u;q.push(v);a[v]=Min(a[u],map[u][v]-flow[u][v]);}}}if (a[t]==0) break;for (u=t;u!=s;u=p[u]){flow[p[u]][u]+=a[t];flow[u][p[u]]-=a[t];}ans+=a[t];}return ans;}int main(){int i,x,y,z,a,b;char c;while(cin>>n>>np>>nc>>m){memset(map,0,sizeof(map));for(i=0;i<m;i++){cin>>c>>x>>c>>y>>c>>z;map[x+1][y+1]=+z;}for(i=0;i<np;i++){            cin>>c>>a>>c>>b;            map[0][a+1]+=b;//输入的时候从0累加。        }for(i=0;i<nc;i++){            cin>>c>>a>>c>>b;            map[a+1][n+1]+=b;//加到n+1去。        }cout<<max_flow(0,n+1)<<endl;//注意这里参数的变化,1变成0,n变成n+1。}return 0;}