网络流学习笔记

来源:互联网 发布:美工笔记本配置2016 编辑:程序博客网 时间:2024/05/22 13:06

代码堆


HDU 1532 Drainage Ditches 

网络流模板题


HDU 3549 Flow Problem

网络流模板题


HDU 3572 Task Schedule

任务分配可行性问题。

观察知:

1:m台机器是不区分的。2:对于每个时刻,至多允许m个任务运行。3:每个任务的[bg,ed]区间,只要被运行p次,该任务就完成了。

so:

对时间建点,

从s对每个任务点建一条cap为p的边,

每个任务点对[st,ed]区间内的时间点各连一条cap为1的边,

每个时间点对t连一条cap为m的边,

判断最大流是否等于sigma(p)。


HDU 2732 Leapin' Lizards

在最外围补一圈网格,将网格看做图上的点,

对曼哈顿距离<=d的(u,v)点对建cap为INF的边,

从源点向包含‘L’的点建cap为1的边,

从最外围一圈点向汇点建容量为INF的边,

由于每个格子有经过限制,将格点拆成入点和出点,从入点向出点连cap为限制数量的边。

注意拆点后原来指向该点的边都指向入点,该点指出的边都改为从出点出发。


HDU 3338 Kakuro Extension

白格填的数对左方黑格和上方黑格的影响是等同的,这转化到图的思想就是入度等于出度。

那么就横进竖出跑最大流。

对横向黑格和竖向黑格分别建点,

源点与横向黑格点连cap为(黑格val-横向白格数)的边,

竖向黑格点与汇点连cap为(黑格val-竖向白格数)的边,

横向黑格点与竖向黑格点连cap为8的边。

题目保证一定有解,即上述建图能满流。

把黑白格分别看做点和边,略微有点叼。保存下白格所对应的反向弧id,就可以打印路径了。

因为白格的值只能是1~9,因此要先手动去掉1点使得范围变成0~8,保证零流是可行流。


HDU 2883 kebab

跟前面那道Task Schedule类似的任务分配问题,不同的地方在于这题的时间范围是100W级别的。

既然不能对单个时间建点,那么就对区间建点好了。

将[bg,ed]离散化,得到最多2*n-1个小区间,并且顾客的区间与这些小区间只有包含和相离关系,

这样我们就可以只需要关心这个小区间完成了多少kebab,而不需要关心它内部是怎样分配时间的。

源点对顾客点连cap为ni*ti的边,

顾客点对他所包含的区间点连cap为INF的边,

区间点对汇点连cap为(ed-bg)*m的边,

检查源点是否满流。


HDU 3605 Escape

只有10个星球,所以根据星球的选择方式一共有2^m种人类,1024 << 10W。

源点对2^m个人类点连cap为该种人数量的边,

人类点对可达星球点连cap为INF的边,

星球点对汇点连cap为居住上限的边,

检查源点是否满流。

tips:如果没有快速读入,记得别交g++。


HDU 4183 Pahom on Water

来回不走重复点,也就是从起点到终点的两条中途不相交路径。

需要拆点保证每个点最多被经过1次。

源点对起点的出点连cap为2的边,

终点的入点对汇点连cap为2的边,

每个点的入点对出点连cap为1的边,

每个点的出点对可达点的入点连cap为1的边,

检查最大流是否为2。


HDU 4240 Route Redundancy

答案为最大流除以流最大路径的容量。

流最大路径的容量:spfa跑一遍原图存下路径最大值就可以求出来了。


HDU 3081 Marriage Match II

可以通过floyd一次求出每个女孩和每个男孩之间能不能有关系。

然后二分答案ans,

源点对每个女孩点连cap为ans的边,表示女孩要选出ans个男朋友,

每个男孩点对汇点连cap为ans的边,表示男孩只能被选ans次,

每个女孩点对可达男孩点连cap为1的边,表示女孩最多只能选择一个男孩一次,

检查满流则当前ans可行。


HDU 3277 Marriage Match III

比上题多了一个女孩选择的方法:额外多了K次选择不是朋友的男孩作为男朋友的机会。

那么就将所有女孩拆点,

对每个女孩,

原点向新点连cap为K的边,

新点向非朋友连cap为1的边,

其他同上题。

注意范围比上题略大一点,其实没什么影响。


HDU 3416 Marriage Match IV

跑最短路,

然后对dis[v]==dis[u]+w(u,v)的关系建u到v的cap为1的边,

跑最大流为答案。


HDU 3468 Treasure Hunting

题意是这样的:按照顺序走最短路访问ABCD..Zabcd..z点,相邻两个字母的路径上只允许挖走一块金子,并且每个点只能被挖一次。问最多能获得多少金子。

若有点不可达,输出-1。

其实就是路径和金子的最大流问题。

源点对路径点连cap为1的边,

路径点对在该最短路径上的金子点连cap为1的边,

金子点对汇点连cap为1的边,

最大流为答案。


HDU 3998 Sequence

最长上升序列的长度可以用O(n^2)的dp求出。然后是建图,

每个值只能用一次,所以要拆点。

源点对dp[i]==1的入点连cap为1的边,

汇点对dp[i]==maxdp的出点连cap为1的边,

对满足j<i && val[j]<val[i] && dp[j]==dp[i]+1的j的出点向i的入点连cap为1的边,

入点向出点连cap为1的边。

求解最大流。


HDU 4309 Seikimatsu Occult Tonneru

渣一样的英语活该WA到哭。。

最多只有12条ancient bridge(黄金12宫?),

所以很显然枚举选择ancient bridge的集合,

源点向每个点连cap为人口数的边,

Tunnel的u向汇点连cap为容量上限的边,

对Tunnel和Modern Road的u向v连cap为INF的边,

对当前选择的ancient bridge的u向v连cap为INF的边,

对未选择的ancient bridge的u向v连cap为1的边,

最大流更新答案。


HDU 3472 HS BDC

把26个字母当做点,串当做边,那么题目就转化成:给出一幅包含有向边和无向边的混合图,判断是否存在欧拉通路。

这样来判断:

首先,所有点连通;

然后,把所有边当做无向边后(这是不影响度的奇偶性的),奇度点的个数为0个或2个;

再然后,借助流来判断:

对于欧拉回路:

对于每条无向边(u,v),先把他当做u->v的有向边,并且在容量图中加入一条从v连向u的容量为1的边(若有流经过这条边,则说明原人为选定方向不对),

源点向每个出入度差为负数的点连cap为出入度差相反数/2的边,

每个出入度差为正数的点向汇点连cap为出入度差/2的边,

若上述建图能满流,则此时每个节点的入度都等于出度,说明存在欧拉回路。

对于欧拉通路:在2个奇度点之间连一条无向边,转化为判断欧拉回路。


UVA 10735 Euler Circuit

判断混合图欧拉回路并输出路径。

按照上题的做法判断存在欧拉回路后,打印路径的方法:

容量网络中cap为0的边(u,v)就是原图无向边确定方向后产生的边,所以能借此建出欧拉图,

dfs打印路径:

dfs(u) : 

        for edge belong u:

                if edge.vis==False:

                        edge.vis = True

                        dfs(edge.v)

        stack[++top] = u

for i = top~1:

        print stack[i]


//


CF316C Tidying Up

费用流,二分图

不细说的话初学者可能就不知道为何这里有‘二分图’的模型存在,就和笔者一样- -(好吧我何其弱!)。对于格子(i,j),

将格子按i+j的奇偶性划分成左右两个部分,如您所见,在本题的模型中确实只有左边和右边会有边相连(一双鞋子是满足这样的情况才能搭)

然后,就是建图啦

源点与偶度格子相连,cap为1,cost为0

奇度格子与汇点相连,cap为1,cost为0

偶度格子与其共边的格子(必然为奇度格子)相连,cap为1,cost则根据他们数值上的关系确定,若数值相等,则cost为0,否则cost为1

然后就是CostFlow找漫流的最小费用啦

相信源汇点的边的cap和cost没有什么疑问,这里要尝试解释一下格子匹配的费用问题:

设最终匹配的两个格子原本的数字为a和b,若a==b,则a和b都不需要交换。若a!=b,则两个选择:把a和b中的一个换掉,费用为1;或者把a和b都换成另一个数字c,费用为2。

但是我们怎么会干出把两个都换掉这种事!如果把a和b都换掉,则说明至少有4个数字在这次的操作中被移动,那为什么不固定a和b中的一个,只移动另外三个数字来达到同样的匹配效果。所以费用只会是0和1。

这一题是固定度数的二分图模型,普通spfa费用流1930ms,用zkw费用流则可以做到30ms。


CF277E Binary Tree on Plane

费用流,二分图,KM

每个节点度限制为入度<=1,出度<=2,只有一个点无入度,很裸的二分图模型。

spfa费用流1466ms,zkw费用流4460ms,KM算法30ms。zkw的顶标调整多路增广模式在这种费用基本不一致的图上不是一点慢。


CF237E Build String

费用流


CF164C Machine Programming

费用流,DAG

这题的每个任务的开始时间和结束时间都是固定的,因此,只有两种决策,就是在一个任务的开始时间时,决定要不要做这个任务。

将时间离散化,得到最多tot个时间点,tot最大为2*n。

源点向时间点1连cap为k,cost为0的边,

汇点为时间点tot,

时间点i向时间点i+1连cap为k,cost为0的边,

每个任务的开始时间点向结束时间点连cap为1,cost为-c的边(最小和最大是可以转化的),

跑最小费用最大流,

判断任务是否在最优解里,看对应的容量边是否被使用就可以了。


CF132E Bits of merry old England

费用流,DAG

先建出n+1个时间点0~n,第i和第i+1个时间点之间代表序列第i个数字。

第i个时间点向第i+1个时间点连cap为m,cost为0的边,

将n个数字拆点,

入点向出点连cap为1,cost为-big的边,

时间点i向第i个数字的入点连cap为1,cost为第i个数字的bit数量的边,

第i个数字的出点向时间点i+1连cap为1,cost为0的边,

第i个数字的出点向下一个相同数字的入点连cap为1,cost为0的边,

源点向时间点0连cap为m的边,汇点为时间点n,

跑最小费用流,根据边是否被使用来打印解。

这题的启发是可以用足够大的负费用来使一些点必须被经过,也因此必须保证图没有负环,简单起见建成DAG就可以了。

big的取值要能够保证所有的数字都在最大流的解中,取61足够,不想计算可以取100W。


CF78E Evacuation

最大流,最短路,二分图

源点连科学家,安全点连汇点,科学家连他能跑到的安全点,最大流,over。


HDU3488 Tour

费用流,二分图,KM

从有向图中选择一个权和最小的边集,让每个点都在环中,也就是每个点的入度和出度都是一。


HDU4067 Random Maze

费用流

先贪心选择所有的边,

若a<b,则先选该边,并且在容量图中加入一条反向的cap为1,cost为b-a的边,并且u的出度+1,v的入度+1,

否则,先不选该边,并且在容量图中加入一条正向的cap为1,cost为a-b的边,

对于s和t的特殊性,转化成一般点比较好处理,因此直接s的入度+1,t的出度+1,表示加入一条必选的从t指向s的边,这样所有的点都要满足出度==入度

然后,按照每个点的出入度差,若出度>入度,则向汇点引一条cap为出入度差,cost为0的边,

否则,从源点向该点引一条cap为出入度差,cost为0的边,

跑最小费用最大流,再加上前面贪心选择的结果,就是答案。

(网络流本来就是可以反悔的贪心)


HDU1533 Going Home

费用流,二分图,KM


HDU3435 A new Graph Game

费用流,二分图,卡STL队列

关于哈密顿环,只要保证每个点的入度和出度都为1,就是了。

丧心病狂的卡STL队列,泥煤啊


HDU1853 Cyclic Tour

费用流,二分图

解法和上题一模一样,唯一不同的地方是,这题不卡STL队列。


HDU2686 Matrix

费用流,DAG


HDU3376 Matrix Again

费用流,DAG

虽然范围是上一题的20倍,但是,把点数调到72W+,边数216W+,就勇敢的提交吧。

受流量所限,本质上就是两次spfa的复杂度。


HDU3667 Transportation

费用流

拆边,把u,v,a,c拆成费用分别为a*1,a*3,a*5,a*7,a*9的边,跑费用流,over。


HDU3315 My Brute

费用流,二分图,KM

裸的二分图模型,难点在处理i==j时的优先匹配。其实也很简单,把所有cost放大100倍,然后在i==j的地方让cost减少1,

然后,在最小费用流的过程中,就自动选择i==j的情况了。得到残量图后,求答案就很简单了。


HDU3395 Special Fish

费用流,二分图,KM

这道题很裸的二分图模型,

但是因为求的是最大收益,而没有完美匹配的限制,

如果用最小费用流做,则需要在增广路费用大于等于0时退出增广,

如果用KM做,则需要把临接矩阵初始化成0,而不能是负数。


HDU2448 Mining Station on the Sea

直接费用流,或者最短路然后KM


BZOJ1061 [Noi2008]志愿者招募

费用流,经典题

由不等式转化到等式,再转化到流,叹为观止,详情百度


HDU3947 River Problem

费用流,志愿者招募的树形版,做这题最好先彻底弄懂上面那道志愿者。

在流量图中,用点表示对应原图中该点和父亲之间的边的相关等式。

由于要保证每个未知数在等式组中都只'+' '-' 符号各出现一次

因此在每个节点的父亲处减去该点的等式

则保证了2次的要求

建图:

对于树边u,v,w,从源点向u连(w,0)的边,从v向汇点连(w,0)的边,从v向u连(INF,0)的边

对于需求u,v,l,c,从u向v连(l,c)的边

跑最小费用流,若flow == sigma(w) 则有解,答案为最小费用cost

spfa_cost_flow = 468ms,zkw_cost_flow = 140ms


HDU4406 GPA

上下界费用流

建图是很简单的,源 -> 时间 -> 科目 -> 汇

其中科目到汇的边需要作类似处理n^2费用边的拆边处理,将base分为val的科目的边拆成100-max(val,60)条边,记f(x)为那个公式,每条边的费用为f(x-1)-f(x),由于f(x)是斜率单调减的函数,因此费用流中能保证按绩点的规则选边

要保证不挂科,其实就是一个下界,处理这个下界有两种方法,一种是给60分以下的边负无穷大的费用,保证优先选,

另一种就是所谓的上下界费用流

其实说起来也就那么一回事,对于这题,只要新建一个虚汇,将不及格的边都连向虚汇,先作一次源->虚汇费用流保证虚汇满流,再作一次源->汇求解


HDU4411 Arrest

最短路,费用流

当年误把这题当做DP,自虐了很久很久。。还是太年轻


HDU3046 Pleasant sheep and big big wolf

最小割入门题

求最小的代价把狼和羊分开,连模型都是裸的- -b

咳咳,最大流最小割定理


HDU1565 方格取数(1)

二分图最大点权独立集

最大点权独立集 == 总权和 - 最小点权覆盖集

最小点权覆盖集 == 最小割

最小割 == 最大流

这道题目,按照i+j的奇偶性划分点集,可以得到二分图,那么就是上面提到的东西了

源向偶点连cap为偶点点权的边,

奇点向汇连cap为奇点点权的边,

偶点向原图中相邻的奇点连cap为INF的边,

最大流


HDU1569 方格取数(2)

同上,数据范围稍变大


HDU3820 Golden Eggs

最小割

割的模型真是难描述啊。。

对于格子x与其相邻格子y,若x放金蛋,则要么y不放金蛋,失去y放金蛋的价值,要么y放金蛋,失去g的价值,

转化到图上来说,失去的价值,就是切割一条长度为3的路径的代价,即分离起点终点,也就是所谓'割'。那么本题就可以转化到容量图的最小割来做。

建图:

将每个格子拆点,变成x和x',偶数格子((i+j)%2==0)用x代表金蛋,x'代表银蛋,奇数格子则相反,构建二分图模型

源向x连cap为对应蛋价值的边,

x'向汇连cap为对应蛋价值的边,

x向x'连cap为INF的边,表示一个格子至少要付出一个代价,失去金蛋或失去银蛋,

x向相邻格子的y'连边,若x为金蛋,cap为g,否则cap为s,

答案为sum(a[i][j]+b[i][j]) - MaxFlow()


HDU3491 Thieves

最小割

题意为,点有权值,找到最小权点割集,使s和t分离

那么拆点就好了


HDU3657 Game

二分图最小割

还是网格模型,所以不用脑子想都知道是奇偶分成二分图。。

对于相邻的两个格子x和y,要么放弃x的价值,要么放弃y的价值,要么放弃(val(x)&val(y))*2的价值,转化到图上即路径切割,所以最大权和就是总权-最小割了。

然后对于有些格子必须选的处理:只要保证该格子不会出现在割集里就可以了,那么只要把该格子原本连向源或汇的边容量改成INF,over。

ans = sum(val) - MaxFlow()


HDU3251 Being a Hero

最小割

路径最小割建模,要么断开一些路径,要么放弃顶点,

建图:

将原图上a,b,c的边以a -> b cap为c的形式加入容量图中,

对于每个有权的顶点,向汇点连cap为点权的边,

然后答案为点权之和减(1 -> 汇)最大流

打印割边的话,就从节点1dfs一遍容量图,分成s割集和t割集,然后检查一下位于两个割集之间的正向边是否满流就可以了(注意直接连向汇的边不能计在内)。


HDU3452 Bonsai

最小割

dfs一遍确定每条无向边的方向,然后叶子向汇点连cap为INF的边,求root -> 汇点的最小割就好了。注意特判一个节点的情况


HDU3987 Harry Potter and the Forbidden Forest

边数最少的最小割

一种做法是将原图的边容量c扩大为c*(m+1)+1,然后答案为MaxFlow()%(m+1),这个技巧在最大流的蛮多题都有用到

另一种做法是原图最大流后,修改原图,将满流的正向弧容量变为1,未满流的正向弧容量变为INF,清空反向弧容量,此图的最大流就是答案,原因请自己思考(有一些显然的细节本弱花了一页纸去证明,泪奔)

胡乱想到这么一个东西:跑完最大流后,所有最小割集包含的边都满流。


HDU2435 There is a war

加一条INF边的最小割

先原图做一次(1 | n)最小割,得到两个点集:S集合T集,那么可以知道,如果新边的两个端点都同在一个集合里,是不会增大最小割的,所以这条新边的两个端点u和v一定是一个在S,一个在T。

若A选择(u,v)连边(u属于原图的S,v属于原图的T),那么B有两个选择,把u,v一起切到S割,或者把u,v一起切到T割,所以B的花费是min(  (1,v | n)最小割 , (1 | u,n)最小割 )

对于(1,v | n)最小割的求法,只要在原图的基础上补一条从1到v的cap为INF的边,然后(1 | n)最小割就可以得到(1,v | n)最小割,(1 | u,n)最小割同理,只要连一条(u,n,INF)的边即可。一个稍好的写法是,例如要求(1,u | n)最小割,不用重建图,在原图(1,n)最小割的残余网络上,直接跑(u,n)最大流,可以得到与重建图跑(1,n)最大流一样的效果。

关于最大的答案,A会从T中选择一个v有最大的(1 | v)最小割,从S中选择一个u有最大的(u | n)最小割,然后B从这两个值中选一个较小值,就是答案。

新技能get :若两个点之间有INF边,那么他们必然同在S集或同在T集,反过来说也就是,若要使求最小割中某两个点同在S集或同在T集中,只需要在他们之间连一条INF的边即可(马丹,怎么又是这么显然的东西!弱无止境。。)。然后还有残余网络的利用。


HDU3917 Road constructions

最小割,最大权闭包

每个公司要么不选,失去税收,要么选,失去建桥的代价,大概就是个最小割模型了。

所以源向公司连cap为税收的边,公司向汇连cap为建桥代价的边,

为处理闭包,新建n个地点,

对于每条边(a,b,c,d),公司c向地点b连INF边,地点a向公司c连INF边,

税收总和减最大流为答案

(最小割图中的每一条有向路径都需要合理的存在理由)


HDU3879 Base Station

最小割

构造二分图,左边的点表示原图的点,右边的点表示原图的边

源向点点连cap为点权的边,边点向汇连cap为边权的边

对于原图的边(a,b,c),点a和点b分别向边点i连cap为INF的边

答案为边权和-MinCut()


HDU3061 Battle

最小割

源向正收益点连cap为收益的边

负收益向汇连cap为收益绝对值的边

对于拓扑关系(a,b),a向b连cap为INF的边

答案为正收益和减MaxFlow()


HDU3996 Gold Mine

最小割

建图同上,注意最大流范围long long,输入输出用%I64d


HDU4307 Matrix

最小割

对于线性代数勉强补考通过的本弱菜,要像网上题解那样分析数学式来解决这道题,完全就是不可能的事情。

于是,弱采取了另一种方法:观察- -b

观察能够发现,如果A的某一项i为0,那么Ci的代价就不用付出,同时也得不到B的第i行和第i列的所有价值,这不就是最小割模型吗

构建三列点,分别代表A的n个项,n个列,n个行

源向项点i分别连cap为Ci的边,

项点i分别向行点i和列点i连cap为INF的边,

列点j向行点i连cap为B[i][j]的边,

行点i向汇连cap为B矩阵第i行权值和的边,

答案为sigma(Bij) - MinCut()

点数3002,边数1004000*2,700+ms,也不是很慢


ZOJ3496 Assignment

上下界网络流

题意为求两种流量分布,分别使最大边最小,和最小边最大。

二分边容量上界跑普通网络流以得到第一个答案

二分边容量下界跑上下界网络流以得到第二个答案


HDU4265 Science!

最大流,二分图匹配

题意为要求输出路径的男女搭配问题

首先,最多的游戏次数这个可以通过二分来求得,

然后,从原图中删除所有没有被使用的边,那么剩下的边中包含了ans个边不相交的完美匹配,

然后,ans次二分图匹配,每次求出一组完美匹配,并把用过的边删掉,就是所要求的路径

依据:Hall定理的推论:设G是k正则二部图(k>0),则G有k个边不重的完美匹配

Hall定理:设G是具有二划分(X,Y)的二部图,则G有饱和X的匹配当且仅当对,其中,N(S)表示S的所有邻点之集


HDU4289 Control

最小割

无向边当作两个方向的有向边就好了,因为必然只有一条被使用,需要拆点


HDU4292 Food

最大流

源 -> food -> human1 -> human2 -> drink -> 汇

最大流就是答案


HDU4322 Candy

费用流

如果只有普通糖(即like矩阵为0),那么只要看糖的数量是否足够即可

因此只需要考虑有特殊喜好的糖的分配

如果一个小孩得到x颗他喜欢的糖,若x*K<=B[i],则不会产生糖效果的浪费,但是若x*K>B[i],则最后一颗糖的效果等价于B[i]%K,即效果上的降低

因此,通过最大费用最大流来分配喜好的糖,使得到的快乐值尽量多,然后再用剩下的糖填补空缺,check是否能使所有小朋友满意

0 0
原创粉丝点击