最大流问题

来源:互联网 发布:怎样辨别淘宝评论真假 编辑:程序博客网 时间:2024/06/06 18:16

暂时最大流问题我就先掌握这一种算法吧
基本的最大流问题:

EK算法:(基于BFS)
每一次BFS更新一条路径,虽然都会入队列,但是由于以下条件保证点不会交叉,所以只有一条到终点的路径会更新流量。

if(!res[v] && map[u][v]>flow[u][v])

注意更新flow矩阵的时候是这样的:

while (u != start)            {                flow[pre[u]][u] += res[end];                flow[u][pre[u]] -= res[end];                u = pre[u];            }

表示从flow[pre[u]][u]的这条边的流量可以增加res[end]这么多,反向的流量响应的减少,下一次在计算反向流量的时候也许不等式 mp[u][pre[u]]>flow[u][pre[u]]成立
http://www.cnblogs.com/jackge/archive/2013/04/10/3012182.html
//15MS 2064K

#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;const int VM=220;const int INF=0x3f3f3f3f;int n,m,max_flow;   //max_flow是最大流int map[VM][VM],flow[VM][VM];   // map[i][j]是每条边的容量,flow[i][j]是每条边的流量 int res[VM],pre[VM];    //res[]是每个点的剩余流量,pre[]是每个点的父亲int EK(int src,int des){    max_flow=0;    queue<int> q;    while(!q.empty())        q.pop();    memset(flow,0,sizeof(flow));    //最开始每条边的流量都是0    while(1){        memset(res,0,sizeof(res));  //残余流量得变0,一开始所有点都没流入对吧        res[src]=INF;   //源点嘛,剩余流量无限是必须的...        q.push(src);    //从源点开始进行BFS找增广路        int u,v;        while(!q.empty()){            u=q.front();            q.pop();            for(v=1;v<=m;v++)       //遍历所有点,找可行边                if(!res[v] && map[u][v]>flow[u][v]){    //该点剩余流量为0 且 容量大于流量,也就是找到了新的结点                     pre[v]=u;   //找到新结点,父节点得记录一下吧                    q.push(v);                    res[v]=min(res[u],map[u][v]-flow[u][v]);    //如果u的剩余流量能填满uv就填满,不能的话就把u这点的流量全部流向uv                 }        }        if(res[des]==0)     //如果当前已经是最大流,汇点没有残余流量            return max_flow;        for(u=des;u!=src;u=pre[u]){     //如果还能增广,那么回溯,从汇点往回更新每条走过的边的流量            flow[pre[u]][u]+=res[des];  //更新正向流量   (注意这里更新的是流量,而不是容量)            flow[u][pre[u]]-=res[des];  //更新反向流量        }        max_flow+=res[des];    }}int main(){    //freopen("input.txt","r",stdin);    while(~scanf("%d%d",&n,&m)){        memset(map,0,sizeof(map));        memset(pre,0,sizeof(pre));        int u,v,w;        while(n--){            scanf("%d%d%d",&u,&v,&w);            map[u][v]+=w;   //有重边        }        printf("%d\n",EK(1,m));    }    return 0;}

比较完整的一个做法:
http://www.cnblogs.com/gabo/archive/2012/08/05/2623531.html

原创粉丝点击