最大流问题:
在最大流问题中,容量c和流量f满足3个性质:
容量限制:For each e ∈E:0≤f(e)≤c(e)
斜对称性:f(u,v)=-f(v,u)
流量平衡:For each v ∈V –{s, t}:
求解最大流问题的算法:增广路径算法。
算法思想:从所有边的流量均为0开始不断增加流量,保持每次增加流量后都满足容量限制、斜对称性和流量平衡三个条件.
计算出每条边上容量与流量之差(残量),得到残量图,其中将流量值作为反向边的流量值,如下图所示。
显然,残量图中的边数可以达到原图中的两倍。如原图中c=16,f=11的边在 残量网络中对应正反两条边,残量分别为16-11=5和0-(-11)=11(回顾前面讲的,残量:每条边上容量与流量之差)。
残量边这里还有待补充的,我感觉自己还没很清楚,看图可以知道,已经有的流值直接加在了反向边上,残量才是顺着往前的
前面说了,算法的思想是:在满足那三个条件的情况下,从所有边的流量均为0开始不断增加流量。这就是增广的过程:找到所有从s到t的道路上,所有残量最小的值d(瓶颈值),然后把对应所有边上流量增加d即可。不难验证,如果增广前的流量满足3个 条件,增广后仍然满足。显然,只要残量网络中存在增广路,流量就可以增大。可以证明它 的逆命题也成立:如果残量网络中不存在增广路,则当前流就是最大流。这就是著名的增广路定理。
最小割最大流定理
s-t割:把所有顶点分成两个集 合S和T=V-S,其中源点s在集合S中,汇点t在集合T中。如果把“起点在S中,终点在T中”的边全部删除,就无法从s到达t了。这样的集合划分 (S,T)称为一个s-t割。
割的容量:即起点在S中,终点在T中的所 有边的容量和。
从另外一个角度看待割,从s运送到t的物品必然通过跨越S和T的 边,所以从s到t的净流量等于
这个很好算。由此可以得出结论: 对于任意s-t流f和任意s-t割(S, T),有
下面来看残量网络中没有增广路的情形。既然不存在增广路,在残量网络中s和t并不连通(回顾前面讲的增广路)。当BFS没有找到任何s-t道路时,把已标号结点(a[u]>0的结点u)集合看成S,令T=V-S, 则在残量网络中S和T分离,因此在原图中跨越S和T的所有弧均满载(这样的边才不会存在于 残量网络中),且没有从T回到S的流量(这个是为啥),因此成立|f|≤(S,T)成立
一、二部图最大匹配(Bipartite Matching)
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int MAX_L = 20;
const int MAX_R = 20;
const int MAXN = 40