最大流



▶ 问题 

在一个有向图里,每个路径都有最大容量,通过这个图最多能运输多少货物。默认容量非负,且不能同时存在边(uv)和(vu)。 

▶ 基本思路 

维护一个流网络,初始化为0,不断增加流的值。 

维护一个残存网络(存储分配流后每条边剩余的容量),初始为最大容量。(在以下代码中,没有特别开一个数组存储残存网络,而是通过原容量减去流网络得到残存网络 

通过在残存网络里寻找增广路径(残存网络中从一条从源结点s到汇结点t的简单路径),并且根据这条路径的残存容量(能够为每条边增加的流量的最大值,也就是这条路径经过边的最小容量)来更新残存网络和流网络(在流网络里加上这个值,在残存网络里减去这个值),直到在残存网络中找不到增广路径为止。 

在找不到增广路径时,流达到了稳定状态,也就是横跨任何切割的净流量相同,这个净割线的边流量的和为净流量,注意正向相加,反向相减 

▶ 代码实现 

·基本变量 

  int cap[MAX][MAX];  //记录每条路径的最大容量

  int flow[MAX][MAX];  //记录当前的流网络

  int a[MAX];    //记录当前路径的残存容量(最终的残余容量存储在a[t]中)

int path[MAX];   //路径压缩

int ans=0;    //存储最大流 

memset(cap,0,sizeof(cap));

memset(flow,0,sizeof(flow));

s代表源结点下标,t代表汇结点下标 

  以下过程循环进行,直到残存网络不包括任何增广路径:

·循环结束条件

 

a[t]==0 ,其中t代表汇结点,残余容量仍旧是初始值0,说明残余容量数据没有更新到汇结点处,也就说明找不到增广路径。 

if(a[t]==0) break;

 

·循环具体步骤

 

①利用宽度优先搜索,在残存网络里找到一条增广路径。 

queue<int>q;  //全局变量,bfs使用 

memset(a,0,sizeof(a));  

a[s]=INF;   // 3,4行操作对象是源结点,s代表源结点的下标值

q.push(s);

while( !q.empty() ){

    u=q.front();q.pop();

    for(v=0;v<n;v++){

    if( !a[v] && cap[u][v]>flow[u][v]){

    path[v] = u;

q.push(v);

a[v] = min(a[u],cap[u][v]-flow[u][v]); 

        }

    }

} 

②更新流网络 

for(u=t;u!=s;u=path[u]){

    flow[path[u]][u]+=a[t];

    flow[u][path[u]]-=a[t];

}

③用当前路径残存容量更新最大流 

ans+=a[t];

  

▶ 示例 

  橙色路径为当前的增广路径,图里显示的是残存网络

第一轮循环:

残存容量:12ans = 12

第二轮循环:

残存容量:4ans = 16

第三轮循环:

残存容量:7ans = 23

 

找不到增广路径

最终最大流为23

 

此时的稳定流网络:

 

检测各个切割:

   

   净流量12+11 = 23                                         净流量 12+7+4 = 23

 

     

   净流量11+19-7 = 23                                     净流量19+4 = 23

 

 

▶ 具有多个源结点和汇点的网络

 

构造一个超级源结点和超级源汇点,让超级源结点指向所有源结点,添加一条容量为正无穷的有向边;让所有源汇点指向超级源汇点,添加一条容量为正无穷的有向边。

其余和普通最大流问题解决方法相同。

 

 

*《算法导论》中给出了存在反平行边的处理办法

*这里未引入反向边的概念,《算法导论》中的反向边就是这里的流网络。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值