代码堆
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
入点向出点连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
否则,先不选该边,并且在容量图中加入一条正向的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是否能使所有小朋友满意