网络流 总结
最大流
有时候求最小花费可以转化为总可能花费减掉最大可删去花费(最大流),或者二分答案/二分某个权值最大流验证。
奇怪的游戏
考虑先假定最后棋盘上的数字再验证。每次的操作是加加相邻的格子,所以可以把棋盘黑白染色,这样操作一次给黑白色的数字总和都加了1,放在网络流上就是建二分图,S到点到T建边,增广1流量即为操作一次,验证最大流加上原总数是否等于假定数字之和。对于最终的数字,如果棋盘是奇×奇,列式子:$x*cnt0-sum0=x*cnt1-sum1$,可以解出$x$就是$sum0-sum1$。如果行列中有偶数,那么在$x$满足的情况下$x+1$也满足(选相邻格子一定可以铺满),便可以二分$x$验证。
注意x的值是可以大于原棋盘最大值的(反例易得),在这个地方卡了很长时间。
士兵占领
满足条件是至少那么多士兵,转化为:先把所有可行士兵都选上,在把每行列能删掉的士兵删去,就是跑能删士兵的最大流。
不知道下界费用流能不能跑。
紧急疏散
总时间可以二分。对于每个门,同一时间限制只能过一个人,那么我们把一个门按时间拆点,把每个人连向相应时间内可以到达的门的分点(可以$bfs$预处理最短距离,小于等于分点时间就可以连边),二分时间验证。
最小割
模板:狼抓兔子(对偶图最小割)
切糕:
一开始想错了,打算直接黑白染色然后拆点跑最小费用最大流,然后发现这个限流不好实现。
然后推翻了重想:对于一个格子$(x,y)$,只能有一个高度,先假设没有$D$的限制,可以直接按高度拆点串联起来跑最小割(其实就是最小),有了$D$的限制,就是考虑如何使割掉高度差大于$D$的边不可行,这样的问题考虑加$INF$边。对于格子$(i,j)$高度$k$,把它割了,要保证与他相邻且差$D$以内的点仍能流过,那么建一条边,起点在$(i,j,k)$,终点在$(x,y,k-D+1)$就能满足其间有流(保证相距过远的边不会同时被割)。这样建边是$N^2$的。一开始$N^4$建边T掉了。
employ人员雇佣:
这类问题好像叫二元组建图最小割。就是求最小花费,把每一个点与S点连边表示它在S的代价,与T连边表示它在T的代价,点$x,y$之间的边表示它们不在同一边的代价。如果不割图,整个图的权值和是不合法的(点只能与S,T其中一方连边),也就是说,最终每个点不能同时连接S和T,割以后便可以满足,最小割就是最小代价。这题又是反过来啦,先选所有员工,再考虑不选一个员工的代价以及两员工不再同一集合的代价,获利总和减去最小代价就是最大获利。
happiness:
类似二元组建图,这题加上了自己选科带来的收益。先选中所有状态,再割掉冲突。对于自己不选文/理的代价可以直接与源点/汇点相连,两人之间的代价需要新建节点,与源/汇点连相应流量,分别连向两人无限流量,割掉源/汇点到此新建点的边表示两人不满足同时选文/理(如果两人同时选文/理,源/汇点本来就有连向两人的边了,那么割掉这条边无贡献反而增加了割的大小)。
不同的最小割:
其实这是最小割树。对于一组点对$(x,y)$,它的最小割分成的两个区域S和T,有性质S中的点与T中的点组成点对的最小割是$(x,y)$的最小割,这个可以不断把图分割,分治下去得到树形结构。本题要求不同的最小割,只需要统计出现的最小割就行了。
线性代数:
先转化题意:求矩阵A使得$\sum \limits_{i=1}^N \sum \limits_{j=1}^N a_i*a_j*b_{i,j} -\sum \limits_{i=1}^N a_i*c_i$,也就是说,B中的一个格子能产生贡献,需要他的列号和行号对应A中的数值都为1,C中的一个格子能产生代价,需要对应A中值为1。有变成了人员雇佣一类的题:选中需要代价,两个一起选会产生贡献。那么就可以最小割了。
海拔:
首先最优情况下每一个点的高度是0或1。先想想dp可不可行,发现城市的状态不一定是对头分成两半的形状,可能弯曲很多次,这只能状压了。那么我们再考虑每一条边产生代价的条件:边的两点高度不一。于是就可以用最小割模型。这题的最小割建出来,S和T分别只用连出1条有权值的边,加上原来的网格图是一张平面图,可以转化对偶图跑最短路求最大流。$O(M*\log N)$
费用流
模板:晨跑
80天环游世界:
这类问题严格规定了每个点经过的次数(包括起点在内),考虑拆点限流。我们可以把一个人的总路线拆成许多小段(两点的路)的组合,这些组合之间互相独立。又有每个点次数的限制,假如p点要求经过x次,有t人以p为总起点,应当有$p作为小段起点$x-t$次,作为小段终点x次。这些总起点可以另用一个附加源点限制,给人数个的流量,再连向每个拆点的出点,表示那些点作为小段起点的次数少于作为终点。
星际竞速:
与上题类似,但建边稍有不同。考虑从每个星球瞬移到另一个星球,不必在星球之间建边,直接从源点连向星球出边是等效的。
修车:
考虑每个车产生的贡献:取决与是哪个人员修的,以及这是那个人倒数第几个修的(对后面的修车都有贡献,乘上倍数)。对于每一个技术人员,每一个修车时间(修一次为一单位时间)都是独立的,拆点跑费用流。
美食节:
修车加强版。考虑修车那题建边的不妥之处:一次建出了N^2M条边,但事实上对每次增广来说,对于同一个厨师来说他做倒数第一道菜比倒数第二到菜产生的贡献要少,所以倒数第二道菜是暂时不需的,只有做了倒数第一道菜才连倒数第二到,注意要连向所有的菜。
数字配对:
考虑了拆点但是并不可做,因为拆完以后就没办法限制次数了。不能拆点,想想二分图?着重于本题的特性,$a_j|a_i$并且$a_i/a_j$是质数,那么唯一分解后$a_i$的质因子一定比$a_j$多一个,这样的点之间才有连边。计算每个数的质因子个数,相当与奇-偶连边(能整除时)。二分图上跑最大费用最大流。
千钧一发:
原始思路:对匹配的点对连边,然后找最大完全子图。网上一搜发现是个NP完全性问题。。
这题还是逆着考虑,对不匹配的点对,一定要弃掉一个。这题的冲突为不匹配,
最大权值闭合子图
一定要考虑好是谁限制谁,并且要保证每一个闭合子图都能满足题意才。一般都是把收益连向代价,一般收益不能独立被选。
模板:最大获利
植物大战僵尸:
对于每一个植物,能吃掉的前提:吃掉所有保护它的植物以及它后方的植物。这里直接跑最大闭合子图会有一个问题,就是有环。先dfs一遍,如果一个点能通向一个环(或者在环内)那么这个点打上ban标记,网络流的时候就不经过他了,权值也舍去。
寿司餐厅
从清早做了半个上午,一个条件没看清卡了很长时间:按种数计费而不是个数。看来这种长题面的题还是得仔细看清啊。
对于收益,因为有包含关系,建一个类似树形的结构:(l,r)向(l+1,r)和(l,r-1)连边,点权为相应美味度。对于“叶子”节点,还需连向其代号的权值-M*x^2的点,表示每个序号只计费一次M*x^2,并且”叶子“的权值减去代号x。然后就可以跑最大权值闭合子图了。
有上下界的网络流
这里有点混乱。要求下界满足,就要在附加流中调平流量,一旦附加流的SS、TT能满流,就说明已经可行(但不是最大流,也不是最小流)。如果要最大流,就得在原图残量网络上跑S->T的最大流,最小流跑T->S的。费用流的话把相应的改最大流为最小费用最大流,而可行与最大流的差别是在于对S->T的增广与否。
模板:支线剧情(最小费用可行流)
模板:旅行时的困惑、清理雪道(最小流):
感觉很熟悉的样子。如果每条边只能经过一次的话可能就是贪心问题了。
对于稠密图一定要加当前弧优化。
志愿者招募:
志愿者一次付费可以工作多天,但是网络流无法实现一次购买流多个流量。考虑把每一天串连起来,每天的限流为-A_i(INF-A_i),S连向第一天、N+1天连向T,流量为INF。因为网络流相当与把串连的流量取了个最小值,所以取负数跑出来的是志愿者最多的一天的流量。每个志愿者从他开始的那天连向结束的后一天,流量为INF,费用为C_i。由于存在合法方案,S-T最大流一定为INF,每一天的点的流入流量也是INF(一定可以买够志愿者),这样连边就相当于弥补了一段区间的流量。