本来心情就非常糟糕调月下毛景树把我最后一点写代码的心情调没了
放弃
开始补全网络流.
之前学了普通最大流,那么现在开始补有上下界的网络流.
在普通最大流中,网络里的每一条边都只有流量的上界即边的容量,而引入上下界网络流之后,每个边不但有一个容量,还有一个流量下界.
我们令B(u,v)表示边(u,v)的下界.于是我们可以有表达式:
B(u,v)≤f(u,v)≤C(u,v)
有这个式子可以得到
0≤f(u,v)≤C(u,v)?B(u,v)
至此,我们可以将有上下界的网络流分为几种问题来对待,接下来就分别讨论一下这几种问题.
(以下内容为我阅读2004国家集训队论文《一种简易的方法求解流量有上下界的网络中网络流问题》周源 以及网上的一些文章后总结归纳写出)
Problem.No.1无源汇有上下界的可行流
假设我们现在有一个网络G,但是网络中不存在源点和汇点S,T,但我们要求网络中的任意一个点i要满足流量平衡条件:
∑(u,i)∈Ef(u,i)= ∑(i,v)∈Ef(i,v)
也就是说让我们在给定有上下界的流网络中寻找可行流.
我们令 f(u,v)=B(u,v)+g(u,v)|g(u,v)≥0这样我们就可以保证每条边中的流量一定时刻符合流量下界的要求.
我们将每条边的容量C(u,v)修改一下,变为C′(u,v)=C(u,v)?B(u,v),这样就可以将已知网络转化为一个没有下界只有上界的流网络,上面的g(u,v)也就可以近似的看成一个可行流.
既然我们有∑(u,i)∈Ef(u,i)= ∑(i,v)∈Ef(i,v),f(u,v)=B(u,v)+g(u,v)|g(u,v)≥0那么就可以顺理成章的推理下去
∴∑(u,i)∈E[B(u,i)+g(u,i)]=∑(i,v)∈E[B(i,v)+g(i,v)]
∴∑(i,v)∈Eg(i,v)?∑(u,i)∈Eg(u,i)=∑(i,v)∈EB(i,v)?∑(u,i)∈EB(u,i)
我们设M(i)为流入i的下界和减去流出i的下界和
即为 M(i)=∑(i,v)∈EB(i,v)?∑(u,i)∈EB(u,i)
①若M(i)≥0
则∑(i,v)∈Eg(i,v)=[∑(u,i)∈Eg(u,i)]+M(i)
加入虚拟源点S0,则令C′(S0,i)=M(i)
②若M(i)<0
则∑(u,i)∈Eg(u,i)=[∑(i,v)∈Eg(i,v)]?M(i)
加入虚拟汇点T0,令C′(i,T0)=?M(i)(?M(i)>0).
在我们重新构图的网络中,如果所有g(S0,i)或者g(i,T0)都满载了,则此时g对应原图中的一个可行流f.
因此若要在原网络中寻找一个可行流,我们只需要在修改后的网络中寻找最大流,若最大流能够使得从源点流出的弧满流,那么原图中一定存在可行流,反之不存在.
Problem.No.2有源汇有上下界的可行流
对于这种情况,我们在源点和汇点之间单独连一条边,要求新连的边不存在下界和上界(即下界为0上界为MAXINT).这样原图变成了如同问题1一样的无源汇有上下界的可行流问题.修改图之后,我们所求的流即为从汇点流向源点的流.
Problem.No.3有源汇有上下界的最大流
法1
我们假设原图中存在源点S到汇点T的可行流f,f(u,v)=a,那么我们在汇点T和源点S之间添加一条弧,弧的流量下界B(t,s)=a,弧不存在流量上界,很显然现在的网络中存在可行流,且当前网络是无源汇的.(也就是转化成了Problem2)
我们二分a的值,每次都做一遍最大流,找到最大的amax,使得当前网络在问题2中存在解,则amax即为所求的最大流.
法2
我们在原图的汇点T和源点S间连一条弧,不存在上下界(即下界为0上界为MAXINT),使得原图变成无源汇的网络,再按照Problem1的方法,建立虚拟源点S0汇点T0,做S0→T0的可行流.若存在可行流f1,再拆掉添加的边,做一遍原图中源点到汇点的最大流f2.
由于第一次最大流中求得的f1只是所有满足下界的流量,在残留网络G(S,T)中仍然存在一些自由流(没有和超级源点和超级汇点连接的边)未满,因此最终答案ans=f1+f2
Problem.No.4有源汇有上下界的最小流
法1
与Problem3相似做法二分a,只是我们需要二分的不再是下界a,这里的a变成了上界C(T,S).找到最小的a,就是答案.
法2
也是与Problem3类似,增加虚拟源点汇点,在不添加边的情况下做S0→T0的最大流.而在做完后,再添加从原来的源点和汇点之间的那条边E(T,S)(同样无上界和下界),再次做S0→T0的最大流.若此时从S0流出的边满流,则f(T,S)为所求最小流,否则无解.
结合两个人博客的理解来阐述一下上面的法2:
和求3.有源汇的上下界最大流过程相反,感性理解是:
首先明确,我们的方法是通过加边转化成对任一点都有流量平衡的无源汇的网络,进行求解.
即最终解只能是加上边后,求的无源汇可行流,即T->S这边上的流量. 不改成无源汇的直接求的解是未必正确的,在(1)中已经提到.
然后,因为第一遍做的时候并无这条边,所以S->T的流量在第一遍做的时候都已经尽力往其他边流了. 于是加上T->S这条边后,都是些剩余的流不到其他边的流量. 从而达到尽可能减少T->S这边上的流量的效果,即减小了最终答案.
感觉上第一遍做的既然是不改成无源汇直接求的,应该是错误的?
这里不是错误的. 首先我们的解都是按照第二遍所求的而定,其次这里这样做本质是延迟对T->S这条边的增流.
解决方法:先不增加d->s容量为无穷的边,进行一次maxflow(),如果还没有满流,则加一条(d,s)容量为无穷的边,再进行一次maxflow(),当且仅当所有附加弧满载时,有可行解,解为flow[(d->s)^1](即d到s的后悔边权值)。
事实上对我来说,我觉得在问题三四中法2更好一些,不仅比较好实现(只需要一次次重复调用已有的maxflow()函数),而且应该比法1好调一些(毕竟有个二分我这么沙茶很容易写残啊)
以及再次感谢 2004国家集训队论文《一种简易的方法求解流量有上下界的网络中网络流问题》周源和网上的那些博客.