网络流 最大流java,网络流(五)有上下限的最大流

传送门:

问题模型:

给定一个加权的有向图,满足:

(1)容量限制条件:

1686233f7916e0b3c88b8aed4d3b757ea39.jpg

(2)流量平衡条件:

34648cbac1cd0e959d5b12e7aa716180218.jpg

(2)中的

6adc01ef907e6018edd15fd030961a7a1d9.jpg即除了源汇外,所有点都满足流量平衡条件,则称G为有源汇网络;否则

2ef514b3b2f6657ded37058213788b88e11.jpg,即不存在源汇,所有点都满足流量平衡条件,则称G为无源汇网络。

将这类问题由易到难一一解决:

问题[1] 求无源汇的网络有上下界的可行流

ebd8bb775fe4d39b788a3498c9249c13acb.jpg

由于下界是一条弧上的流必需要满足的确定值。下面引入必要弧的概念:必要弧是一定流要满的弧。必要弧的构造,将容量下界的限制分离开了,从而构造了一个没有下界的网络G’:

1. 将原弧(u,v)分离出一条必要弧:

fcdacae09c0dcc1bba37bd731703a0d4870.jpg。(红色表示)

2. 原弧:

e1c4ca6a098e2f9be180d6672a712265c25.jpg

854b0726dd48b22a9bcc6501c0318824811.jpg

由于必要弧的有一定要满的限制,将必要弧“拉”出来集中考虑:

5c80ea8a05bbb0379fea1398a6cfd166a1e.jpg

添加附加源x, 附加汇y。想像一条不限上界的(y, x),用必要弧将它们“串”起来,即对于有向必要弧(u, v),添加(u, y),(x, v),容量为必要弧容量。这样就建立了一个等价的网络。

6fc1460249433772ab0004ab8a22eed78d1.jpg

一个无源汇网络的可行流的方案一定是必要弧是满的。若去掉(y, x)后,附加源x到附加汇y的最大流,能使得x的出弧或者y的入弧都满,充要于原图有可行流。

6b31d59d576add571e3466ca7dee2ca46ad.jpg

算法:

1. 按上述方法构造新网络(分离必要弧,附加源汇)

2. 求附加源x到附加汇y的最大流

3. 若x的出弧或y的入弧都满,则有解,将必要弧合并回原图;否则,无解。

问题[2] 求有源汇的网络有上下界的可行流

7377628e349f13be356c09614e0a850c62f.jpg

加入边(t, s),下界为0(保证不会连上附加源汇x, y),不限上界,将问题[2]转化为问题[1]来求解。

调用dinic算法

1 bool lowbound_flow(int n, int source, intsink)2 {3 init(n + 2);4 vectortot_in(n + 1), tot_out(n + 1);5 for(int i = 0; i < (int)u.size(); i++)6 {7 if(U[i] < L[i])return false;8 tot_in[v[i]] +=L[i];9 tot_out[u[i]] +=L[i];10 addedge(u[i], v[i], U[i] -L[i]);11 }12 addedge(sink, source, 100000000);13 int super_source = n + 1;14 int super_sink = n + 2;15 for(int i = 0; i < n; i++)16 {17 addedge(super_source, i, tot_in[i]);18 addedge(i, super_sink, tot_out[i]);19 }20 int ans =Maxflow(super_source, super_sink);21 //cout<

22 for(int i = 0; i < G[super_source].size(); i++)23 {24 edge& tmp =e[G[super_source][i]];25 if(tmp.f != tmp.c)return false;//判断是否满流 不满流则错误

26 }27 return true;28 }

8024ec55b9051b907a3462e207e647fbdb8.jpg

问题[3]求有源汇的网络有上下界的最大流

算法:

1. 先转化为问题[2]来求解一个可行流。若可行无解,则退出。由于必要弧是分离出来的,所以就可以把必要弧(附加源汇及其临边)及其上的流,暂时删去。再将(T,S)删去,恢复源汇。

2. 再次,从S到T找增广轨,求最大流。

3. 最后将暂时删去的下界信息恢复,合并到当前图中。输出解。

这样既不破坏下界(分离出来)也不超出上界(第2步满足容量限制),问题解决。

问题[4]求有源汇的网络有上下界的最小流

算法:

1. 同问题[3]。

2. 从T到S找增广轨,不断反着改进。

3. 同问题[3]。

问题[3]与问题[4]的另一种简易求法:

注意问题[2]中,构造出的(t, s),上下界几乎没什么限制。下面看看它的性质:

定理:如果从s到t有一个流量为a的可行流f,那么从t到s连一条弧(t, s),其流量下界b(t, s) = a,则这个图一定有一个无源汇的可行流:除了弧(t, s)的容量为a外,其余边的容量与f相同。

证明:如果从s到t的最大流量为amax,那么从t到s连一条下界b(t, s) = a’ > amax的弧(t, s),则从在这个改造后的图中一定没有无源汇的可行流:否则将这个可行流中的弧(t, s)除去,就得到了原图中s到t的流量为a’的流,大于最大流量amax,产生矛盾。

可以二分枚举这个参数a,即下界b(t, s),每次用问题[1]判断是否有可行流。这样就可以求出最大流。

同理,问题[4]要求最小流,只要二分枚举上界c(t, s)即可。

因为朴素的预流推进算法O(N3),总复杂度为O(N3 log2流量) 。

思路:

无源汇 (附加源汇+最大解决)

有源汇 (附加(T,S)->无源汇)

求有源汇的网络有上下界的最大流:(s-u v-t之间的路省略了)

d50ffb66cc76c292cc3e3905e0767696.png

(1)对于每条边,拉出一条必要弧(下限)

8357b011c7905ddfdcc6a4c65ebf2a45.png

(2)去除T到S的边,然后求S-T的最大流F0

bb18c1002a1c7ea2d418fcc1e4d6017b.png

(3)如果S-T的最大流使得所有的S出边流量满,T的入边流量满,问题有解,否则无解

两者只要有一者是满的,另一个一定是满的,因为总的出流量=总的入流量

有解的时候F0 = 所有下界之和

(4)如果有解,在原来S-T的最大流网络的基础上,删去所有与S和T相连的边,并且剩下的每条边的流量都加上下限值,在此基础上继续扩充找增广路,最终的得到的答案就是最大流

挑战中介绍了第4步另一种方法,直接在S->s连+INF的边,t->T连+INF的边,再求一遍S-T的最大流F,那么原图最大流为F-F0(也就是F-下界之和)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值