仔细思考了一下,发现自己还有许多弱项,网络流也是其中之一,而且只会写板子,需要补一补。
还有10天就GDOI了,要抓紧啊……
注意:以下某些题没有写代码,只是口胡后看了题解发现差不多,不保证完全正确。
本专题的题单来自 https://www.cnblogs.com/xht37/p/10457051.html ,Orz神仙
二分图
洛谷P1402 酒店之王
把每个人拆成两个点放在中间,左边房子右边菜,跑最大流即可。
洛谷U64949 棋盘覆盖
黑白染色之后发现只能黑和白匹配,于是就是个二分图了,搞出最大匹配即可。
套路:黑白染色之后有可能会成为二分图。
洛谷U64970 車的放置
把行和列作为点,格子作为边,如果可以放就把对应的行列连起来,然后跑最大匹配。
这样的匹配显然满足所有车都不同行不同列。
套路:行列作为点,格子作为边。
洛谷P1129 [ZJOI2007]矩阵游戏
注意到一个性质:无论怎么换,同行的黑点仍然同行,同列的黑点仍然同列。
所以每行/列最多有一个黑点在对角线上。
那么和上一题一样的建图方法就可以做了。
洛谷P1963 [NOI2009]变换序列
显然在\(D(i,T_i)\)确定的情况下能与\(i\)匹配的\(T_i\)是常数级别的。
那么连一下二分图就可以得到一组解了。
用匈牙利算法,从后往前做,就可以字典序最小了。
UVA1194 Machine Schedule
考虑最终答案就是AB不同状态个数的和,也就是要用最少的状态,使得每个任务都被覆盖。
把A状态放左边,B状态放右边,每个任务视为一条边,那就是求这个二分图的最小点覆盖。
定理:二分图最小点覆盖包含的点数 == 二分图最大匹配包含的边数。
于是跑一个最大匹配就做完了。
套路:对于二者至少选其一的限制,将其视为边,做最小点覆盖。
POJ2226 Muddy Fields
一个显然的贪心:对于每一个木板,肯定会一直变长直到顶到边界或干净格子。
所以每个泥泞格子至少会被横着或竖着的两种木板之一覆盖。
用上一题的定理和套路就做完了。
洛谷P3355 骑士共存问题
按套路黑白染色一下,发现限制只会在黑白点之间,于是就变成了求二分图的最大独立集。
定理:设\(G\)是有\(n\)个节点的二分图,\(G\)的最大独立集大小 == \(n-\)最小点覆盖数 == \(n-\)最大匹配数。
那么就做完了。
洛谷P2423 [HEOI2012]朋友圈
首先发现朋友圈就是一个团。
然后发现A国是一个二分图,B国是两个团之间连了一些边。
定理:无向图 \(G\) 的最大团 == 补图 \(G'\) 的最大独立集。
发现A国最多选两个人,B国取个补图就变成了二分图。
那么可以枚举A国的人,把B国和他们是朋友的人提出来搞个补图,然后求补图(一个二分图)的最大独立集即可。
UVA1327 King's Quest
显而易见的思路是枚举每组喜欢关系,然后匈牙利算法判一下是否合法,不过貌似会T。
考虑优化判合法的过程。对于给定的方案\(x_i\rightarrow y_i\),连一条\(y_i\rightarrow x_i\)的边,然后再把喜欢关系的边\(x_i\rightarrow y_i\)连上。
那么\(x_i\rightarrow y_j\)合法当且仅当\(x_i,y_j\)在同一强连通分量里,考虑匈牙利算法的实现过程,这显然正确。
那么就做完了,复杂度\(O(n+m)\)。
洛谷P2764 最小路径覆盖问题
定理:有向无环图的最小路径点覆盖包含的路径条数 == \(n-\)其拆点二分图的最大匹配数
于是做完了。
有向无环图的最小可重复路径点覆盖
首先求出每个点能到达哪些点(说得高端一点就是进行传递闭包)。
然后往能到的点都连上边,就变成最小路径点覆盖了。
洛谷P2765 魔术球问题
考虑拆点,若\(x\)之后可以接\(y\)则连边\(x\rightarrow y'\)。
总数减去最大匹配数就是需要的柱子数。
那么可以一直加球,直到需要的柱子数超过\(n\)时停止。
(感受一下,这其实就是DAG的最小路径覆盖)
最大流
洛谷P2472 [SCOI2007]蜥蜴
把每一个石柱拆成入点出点,之间连上该石柱的高度的权值的边。
源点连蜥蜴位置,能跳出去的位置连汇点,位置之间互相连。
跑最大流即可。
套路:点有权值时拆点连边,转化为边的权值。
洛谷P2766 最长不下降子序列问题
第一问乱搞即可。
第二问
设以\(i\)为结尾的序列最长长度为\(f_i\)。
连边:\(i-i',[if\ f_i=1]S-i,[if\ f_i=mx]i'-T,[if\ a_i\le a_j\&\&i<j\&\&f_i+1=f_j]i'-j\),权值均为1.
跑最大流即可。
第三问
把有关1、n的流量限制全都设为\(\infty\),再跑一遍最大流即可。
注意特判n=1!
洛谷P2754 [CTSC1999]家园
从小到大枚举需要的时间。飞船可以视为每到一个地方就所有人都下去,然后再考虑是否上来。
按时间拆点:设\((x,i)\)表示\(i\)时刻在\(x\)点。
每个时间可以算出某个飞船是从\(x\)到\(y\),那么连一条\((x,i)\rightarrow (y,i+1)\),权值为飞船容量的边。
也连一条\((x,i)\rightarrow (x,i+1)\),权值\(\infty\)的边,表示呆在原地不动。
然后以地球为\(S\),月球为\(T\)跑最大流,看是否能转移所有人。
最小割
定理:最大流=最小割。
UVA1660 Cable TV Network
首先枚举不连通的两点。
拆点,把每一个点拆成入点和出点,之间连权值为1的边。割开这条边就等价于删点。
然后跑最小割即可。
洛谷P2774 方格取数问题
黑白染色,发现只有黑白点之间会互相影响。
相邻的黑白点连权值\(\infty\)的边表示不能割开,\(S\)往黑点连权值为格子权值的边,白点往\(T\)连权值为格子权值的边。
用总权值减去最小割就是答案了。
图的意义:割开的边表示不选这个格子。
最后分成了两部分,选了与\(S\)相连的黑点、与\(T\)相连的白点。
套路:最小割常用于表示分开两种不同状态。
洛谷P2057 [SHOI2007]善意的投票
源点连想睡觉的人,不想睡觉的人连汇点,朋友之间连边,权值均为1。然后跑最小割即可。
图的意义:跑完最小割后分成了想/不想睡觉两个集合,割开的边表示与自己意愿或以朋友的票冲突
洛谷P2598 [ZJOI2009]狼和羊的故事
源点连羊,汇点连狼,相邻点之间连边,权值均为1。然后跑最小割即可。
图的意义:要把羊和狼隔开,割边表示在对应交界处建篱笆
洛谷P4126 [AHOI2009]最小割
模板题,求最小割的可行边和必须边。
首先求最大流,那么可行边和必须边都是满流的。
可行边:残量网络中不存在\(x\rightarrow y\)的路径。(tarjan即可)
必须边:残量网络中存在\(S\rightarrow x,y\rightarrow T\)的路径。
洛谷P2046 [NOI2010]海拔
发现题目很奇怪地让我们答案保留整数,于是大胆猜结论:海拔只有0和1。
很显然,最优解是左上0右下1,中间以一条分割线隔开。
那么这就是个最小割模板,但会TLE。
定理:平面图最小割=对偶图最短路。
那么建出对偶图之后就做完了,注意方向。
(我的建法:左下\(S\),右上\(T\),一条边左边0,右边1,好像和题解差不多。)
费用流
洛谷P2045 方格取数加强版
每个点拆成入点出点,中间连\(k\)条边,一条费用为原权值,剩下的为0。每个点向右下连边。
直接最大费用最大流即可。
洛谷P2053 [SCOI2007]修车
因为不知道后面会有多少人等,所以不能直接连边。
逆向考虑:每个人倒数第几个被修?
知道自己倒数第几个被修就好做了。把工人\(i\)拆成\((i,j)\),表示倒数第\(j\)个被修,然后随便连一连、匹配一下,就做完了。
洛谷P2050 [NOI2012]美食节
基本同上,但头铁跑费用流会TLE。
优化:每跑一次就加一层点,复杂度较为玄学,但能过。
洛谷P2604 [ZJOI2010]网络扩容
第一问直接最大流即可。
对于第二问,利用第一问的残量网络。原来剩下的费用为0,新加的流量\(\infty\),费用\(w\)。
最后限制一下最大流为\(k\),跑最小费用最大流即可。
洛谷P2153 [SDOI2009]晨跑
由于每个点只能经过一次,那么把点拆成入点出点,之间连流量1费用0的边。
点之间连流量1费用\(w\)的边。
跑最小费用最大流即可。
洛谷P2469 [SDOI2010]星际竞速
一开始想到了有上下界费用流,似乎也能过(有题解)。
但正解还是普通费用流。
考虑每跳跃一次就视为重新开始了一次,那么这相当于DAG的带权最小路径覆盖。
一开始令答案为点权和,表示全都靠跳跃。然后拆点\(S\rightarrow x,x'\rightarrow T\),对于原图\(x\rightarrow y\)连边\(x\rightarrow y'\),费用为\(w_e-w_y\),表示消去了跳跃的时间、加上了边的时间。跑最小费用流即可。注意费用为正时直接停止。
洛谷P2770 航空路线问题
首先要看对题:起点终点都是确定的。
然后这题就转化为:求总长最长的\(1\rightarrow n\)的不相交的两条路径。
按套路拆点,费用1流量1,表示只能经过一次。有航线就连边,费用0流量1。外面\(S\rightarrow 1\)限制流量2,防止多流。
然后跑最大费用最大流就是最长路径了。
输出方案应该不难,最多有点坑而已。
洛谷P3358 最长k可重区间集问题
竟然没做出来?
感性理解一下,似乎每一种方案都可以拆成\(k\)种方案,其中每个方案的线段都不相交。
于是就变成方格取数了。
把端点离散化一下,相邻的连边,左端点连右端点,限制最多跑\(k\)次。然后跑最大费用流即可。
(这题我感觉应该是这么理解的,但不太会证明,仅供参考)
洛谷P3357 最长k可重线段集问题
很好我又没做出来……
建图方法几乎和上面一样,但注意\(x_1=x_2\)时你会连出自环来。
把点拆成入点出点就好了,\(x_1=x_2\)时入点连出点。
洛谷P4016 负载平衡问题
源点连货物有多的点,货物少的点连汇点,相邻仓库互相连,跑最小费用最大流即可。
有上下界网络流
无源汇有上下界可行流
每条边预先流掉下界,但会导致流量不平衡。
设流进来的-流出去的为\(d_x\)。
设立超级源、汇,若\(d_x>0\)则连\((S,x,d_x)\),否则连\((x,T,-d_x)\),跑最大流。
能跑满则每条边的流量+下界就是可行流。
有源汇有上下界最大流
连\((T,S,\infty)\)变为无源汇,然后跑一次无源汇有上下界可行流。
然后从\(S\)往\(T\)跑就得到了最大流。注意一开始加的边不要删!
无源汇有上下界最小流
连\((T,S,\infty)\)变为无源汇,然后跑一次无源汇有上下界可行流。
然后减去\(T\)往\(S\)跑的最大流就得到了最小流。注意一开始加的边要删!
费用流
和上面差不多,只不过加上了费用。
洛谷P3980 [NOI2008]志愿者招募
对于每个时间连\(i\rightarrow i+1\),费用0,下界\(a_i\)。
对于每个志愿者\((l,r),w\)连\(r+1\rightarrow l\),费用\(w\)。
然后跑无源汇有上下界最小费用可行流。
这种环流的建图方法真是骚呢。
洛谷P4553 80人环游世界
按套路拆点,入点出点之间上下界均为\(V_i\),\(S\)连向所有点,所有点连向\(T\),点之间连边。
外面设一个超级汇,连\(T\rightarrow T'\),上下界均为\(m\)。
然后跑有源汇有上下界最小费用可行流。