题解合集,题目来源于本校题库。
如果想要原题或SPJ,可以向[email protected]发邮件。
学校题库上的要求可能与原题不同,我将标注出来,并以本校题库为主。
注:所有最大流的实现均为Dinic算法,费用流的实现均为Edmonds Karp算法,连边均为有向边。
裸二分图匹配,可以直接Hungary算法。也可以上最大流。
建立源点 S S S和汇点 T T T, S S S向所有外籍飞行员连流量为 1 1 1的边,所有外籍飞行员向能与之配对的英国飞行员连流量为 1 1 1的边,所有英国飞行员向 T T T连流量为 1 1 1的边,跑 S S S到 T T T的最大流。答案即为最大流。
本校题库并未要求输出方案。Hungary输出result数组,最大流跑一边满流边即可。时间复杂度为 O ( n e ) O(ne) O(ne)(Hungary)或 O ( n e ) O(n\sqrt e) O(ne)(Dinic)。
Code
最大权闭合图问题。转化为最小割问题。然后根据最大流=最小割,即为求最大流问题。
建立源点 S S S和汇点 T T T, S S S向每个实验连流量为该实验收益的边,每个实验向对应的仪器连流量为无穷大的边,每个仪器向 T T T连流量为仪器花费的边。答案为所有实验花费减去 S S S到 T T T的最大流。
下面是正确性解释(By Byvoid):
定义一个割划分出的S集合为一个解,那么割集的容量之和就是(未被选的A集合中的顶点的权值 + 被选的B集合中的顶点的权值),记为Cut。A集合中所有顶点的权值之和记为Total,那么Total - Cut就是(被选的A集合中的顶点的权值 - 被选的B集合中的顶点的权值),即为我们的目标函数,记为A。要想最大化目标函数A,就要尽可能使Cut小,Total是固定值,所以目标函数A取得最大值的时候,Cut最小,即为最小割。
原题要求输出实验方案,本校题库未要求输出。方案即为 S S S的最大流路径上的点。时间复杂度 O ( ( n + m ) 2 e ) O((n+m)^2e) O((n+m)2e)。
Code
题干说的什么玩意,最后求一个最大流…
对于原图的每一个点拆成两个点 x , y x,y x,y, x , y x,y x,y之间连流量为无穷大的边,建立源点 S S S和汇点 T T T, S S S向每个 x x x连接流量为 1 1 1的边,每个 y y y向 T T T连接流量为 T T T的边,跑 S S S到 T T T的最大流。答案为原图点数减最大流。
下面为正确性解释(By Byvoid):
对于一个路径覆盖,有如下性质:
1、每个顶点属于且只属于一个路径。
2、路径上除终点外,从每个顶点出发只有一条边指向路径上的另一顶点。
所以我们可以把每个顶点理解成两个顶点,一个是出发,一个是目标,建立二分图模型。该二分图的任何一个匹配方案,都对应了一个路径覆盖方案。如果匹配数为0,那么显然路径数=顶点数。每增加一条匹配边,那么路径覆盖数就减少一个,所以路径数=顶点数 - 匹配数。要想使路径数最少,则应最大化匹配数,所以要求二分图的最大匹配。
注意,此建模方法求最小路径覆盖仅适用于有向无环图,如果有环或是无向图,那么有可能求出的一些环覆盖,而不是路径覆盖。
原题要求输出方案,本校题库并未要求。方案即为 S S S出发的所有满流边,每条满流边上的点。时间 O ( n 2 e ) O(n^2e) O(n2e)。
Code
转化为答案判定性问题,二分答案,把每个球看成一个点,如果这两个球可以相邻,就将这两个球连接起来,建立源点 S S S和汇点 T T T,就可以同上一题了。注意连接有向边时有序,可以小编号向大编号连边,亦可以从大往小连接。
原题要求输出方案,本校题库未要求。方案输出同上题。
时间复杂度 O ( m a x a n s 2 e log 2 m a x a n s ) O(maxans^2e\log_2 maxans) O(maxans2elog2maxans)
Code
最大流问题,建立源点 S S S和汇点 T T T, S S S向每个单位连流量为单位人数的边,每个单位向每张桌子连流量为 1 1 1的边,每张桌子向 T T T连流量为桌子容量的边,跑 S S S到 T T T的最大流。如果最大流与单位代表数相等,即为有解,否则为无解,若有解,对于每一个公司,若对于一张桌子满流则为有人坐这张桌子,输出之。时间复杂度为 O ( ( n + m ) 2 ( n m + n + m ) ) O((n+m)^2(nm+n+m)) O((n+m)2(nm+n+m))。此题有SPJ。
Code
第一问经典DP题, O ( n 2 ) O(n^2) O(n2)处理出以 i i i为终点的最长递增子序列长度;
第二问最大流,对于一个位置拆成两个点 x , y x,y x,y, x , y x,y x,y连接流量为 1 1 1的边,建立源点 S S S和汇点 T T T,对于每个位置,如果它的 d p [ i ] = 1 dp[i]=1 dp[i]=1,由 S S S向 i . x i.x i.x连流量为 1 1 1的边,如果它的 d p [ i ] = a n s dp[i]=ans dp[i]=ans(ans为第一问答案),则由 i . y i.y i.y向 T T T连流量为 1 1 1的边,跑 S S S到 T T T的最大流;
第三问就是把 S S S向位置 1. x 1.x 1.x, 1. x 1.x 1.x向 1. y 1.y 1.y, n . x n.x n.x向 n . y n.y n.y, n . y n.y n.y向 T T T的边流量设为无穷大,再跑 S S S到 T T T的最大流。
时间复杂度为 O ( n 2 + n 4 ) O(n^2+n^4) O(n2+n4),显然数据并没有达到最坏复杂度,并且Dinic跑网络流速度玄学。
Code
类似圆桌问题的建边,建立源点 S S S和汇点 T T T, S S S向每个类别连接流量为需要题目数的边,每个类别向所属的题目连流量为 1 1 1的边,每道题向 T T T连流量为 1 1 1的边。跑 S S S到 T T T的最大流。输出类似圆桌问题,同样有SPJ。
本校输出为:
输出组卷方案。如果有解则在第一行输出1,文件第 i + 1 i+1 i+1行输出类型 i i i的题号。如果有多个满足要求的方案,只要输出1个方案。如果问题无解,则输出0。(为方便SPJ,输出与原题输出不同)
时间复杂度为 O ( ( n + k ) 2 e ) O((n+k)^2e) O((n+k)2e)
Code
大神题,至今没人用网络流解出(解出的都是错的…),可以网搜参考一些玄学IDA*等算法。数据可能有误。
因为方格均需不相邻,所以将棋盘黑白染色,所有相邻格子的颜色互不相同,建立源点 S S S和汇点 T T T,如果为白点, S S S向这个点连流量为这个格子的数的边,如果这个点为黑点,这个点向 T T T连流量为这个格子的数的边。然后这个点向四周的格子连边,注意只能白点向黑点连边,然后求全图最小割(其实就是 S S S到 T T T的最大流),然后用所有数字之和减去最小割即为答案。时间复杂度为 O ( ( n m ) 2 e ) O((nm)^2e) O((nm)2e)
Code
最小费用最大流问题。对于每天拆成两个点 x , y x,y x,y, x , y x,y x,y之间没有边。建立源点 S S S和汇点 T T T。对于每一天 i i i, S S S向 i . x i.x i.x连流量为该天需要餐巾数,费用为 0 0 0的边, i . y i.y i.y向 T T T连流量为该天需要餐巾数的边。对于 i + 1 ≤ N i+1\le N i+1≤N的天, i . x i.x i.x向 ( i + 1 ) . x (i+1).x (i+1).x连接流量无穷大,费用为 0 0 0的边,对于 i + m ≤ N i+m\le N i+m≤N的天, i . x i.x i.x向 ( i + m ) . y (i+m).y (i+m).y连流量无穷大,费用为 f f f的边,对于 i + n ≤ N i+n\le N i+n≤N, i . x i.x i.x向 ( i + n ) . y (i+n).y (i+n).y连流量无穷大,费用为 s s s的边,对于任意天, S S S向 i . y i.y i.y连流量无穷大,费用为 p p p的边。然后跑 S S S到 T T T的最小费用最大流即可。时间为 O ( N e 2 ) O(Ne^2) O(Ne2)。
Code
接着拆点,对于每个城市拆成两个点 x , y x,y x,y,除了 1 1 1号城市和 n n n号城市,每个城市 i i i的 i . x i.x i.x向 i . y i.y i.y连流量为1,费用为0的边, 1. x 1.x 1.x向 1. y 1.y 1.y连流量为2,费用为0的边, n . x n.x n.x向 n . y n.y n.y连流量为2,费用为0的边,对于每条航线连接的两个城市 c 1 , c 2 c1,c2 c1,c2,规定 c 1 < c 2 c1
Code
二进制压状态,把每个二进制状态当做点,跑最短路即可。可以隐式建边,用二进制判断是否可以转移。网上题解多得是我就不说了。时间复杂度 O ( ( n + m ) 2 n ) O((n+m)2^n) O((n+m)2n)。
Code
这根本不是网络流啊。
CTSC1999太深了。(这是第一个)
像魔术球问题一样,二分答案,变成答案判定性问题。首先判断是否有一条从地球到月球的路线,如果没有果断无解,这个判断可以并查集完成。
二分答案的判定靠最大流判,如果这个答案为 d d d,则对于每个太空站 i i i拆成 d + 1 d+1 d+1个点,分别为 0 − d 0-d 0−d天。记为 < i , d > <i,d>建立源点 S S S和汇点 T T T,对于每一天, S S S向 < 0 , d > <0,d> <0,d>连流量无穷大的边, < − 1 , d > <-1,d> <−1,d>向 T T T连流量无穷大的边,如果这天不是第0天,如果太空船第 d − 1 d-1 d−1天在 x x x太空站,第 d d d天在 y y y太空站,则 < a , d − 1 > <a,d−1>向 < b , d > <b,d>连流量为太空船容量的边,对于每个太空站 i i i, < i , d − 1 > <i,d−1>向 < i , d > <i,d>连流量为无穷大的边。求 S S S到 T T T的最大流。
时间复杂度 O ( v 2 e log 2 m a x a n s ) O(v^2e\log _2 maxans) O(v2elog2maxans)。
还是CTSC1999的题。
Code
这TM不是拯救大兵瑞恩那道题吗(又又又是CTSC1999)(我出生那年的CTSC发生了什么…)。
潜入辛迪加做过吗?
没做过?
分层图,对于原图建立出 2 p 2^p 2p层,每层表示一种钥匙取得的状态。对于每个钥匙点,如果有状态没有获得这个钥匙,便可以由没有这个钥匙的状态转移到获得了这个钥匙的状态,代价为0。于是建边,边权为0。对于可以走到空地的格子,对于 2 p 2^p 2p层图都连边权为1的边,对于到达另一个格子需要钥匙,对于每一个已获得这种钥匙的状态,连边,边权为1。然后对这么多点跑个最短路即可。答案为可达 ( N , M ) (N,M) (N,M)的状态中距离最小值。时间复杂度大概是 O ( n m 2 p ) O(nm2^p) O(nm2p)。
Code
接着分层图,建立 K K K层图,记在地图上位置为 i i i,剩余油量为 l e f t left left的状态为 < i , l e f t > <i,left>,则建边如下:
1、如果油箱不满( l e f t < K left
2、如果油箱不满( l e f t < K left
3、如果油箱不空( l e f t > 0 left>0 left>0)且 i i i为油库点, < i , K > <i,K>向 < j , K − 1 >
4、如果油箱不空( l e f t > 0 left>0 left>0)且 i i i不为油库点, < i , l e f t > <i,left>向 < j , l e f t − 1 >
然后就是求个最短路了…答案为 d i s [ < ( n , n ) , i > ] dis[<(n,n),i>] dis[<(n,n),i>]的最小值。时间复杂度 O ( n 2 k ) O(n^2k) O(n2k)。
Code
最大费用最大流问题,对于每个点 i i i,拆点 x , y x,y x,y,如果允许一个点走多次,则 i . x i.x i.x向 i . y i.y i.y连流量为无穷大,边权为数字的边,否则 i . x i.x i.x向 i . y i.y i.y连流量为1,边权为数字的边。然后向左下和右下连边,如果路径允许相交,则 i . y i.y i.y向 j . x j.x j.x连流量为无穷大,边权为0的边,否则 i . y i.y i.y向 j . x j.x j.x连流量为1,边权为0的边。建立源点 S S S和汇点 T T T, S S S向第一行的所有数 i . x i.x i.x连流量为1,边权为0的边,对于可以路径相交,最后一行所有数 i . y i.y i.y向 T T T连流量为无穷大,边权为0的边,否则流量为1。然后求 S S S到 T T T的最大费用最大流。时间复杂度为 O ( v e 2 ) O(ve^2) O(ve2)。
Code
接着费用流,建立源点 S S S和汇点 T T T, S S S向每个仓库连接流量为货物数,边权为0的边,每个零售店向 T T T连接流量为所需货物数,边权为0的边。对于每个仓库和商店,连接流量为无穷大,费用为转移花费的边,先跑 S S S到 T T T的最小费用最大流,再跑最大费用最大流。时间为 O ( ( n + m ) ( n m ) 2 ) O((n+m)(nm)^2) O((n+m)(nm)2)。
Code
还是费用流,建立源点 S S S和汇点 T T T, S S S向每个人连接流量为1,边权为0的边,每个任务向 T T T连接流量为1,边权为0的边。对于每个人和任务,连接流量为1,费用为工作费用的边,先跑 S S S到 T T T的最小费用最大流。时间为 O ( ( n + m ) ( n m ) 2 ) O((n+m)(nm)^2) O((n+m)(nm)2)。原题还得跑个最大费用最大流,本校不用跑这问。
Code
费用流(多少个了…),因为要使仓库的库存数量相同,所以这个数值便是仓库的库存数量的平均值,记平均值为 x x x,建立源点 S S S和汇点 T T T, S S S向 i i i仓库连接费用为0,流量为原库存量的边, i i i仓库向 T T T连费用为0,流量为 x x x的边,然后向前一个和后一个仓库连流量为无穷大,费用为1的边,跑 S S S到 T T T的最小费用最大流。时间复杂度为 O ( n 3 ) O(n^3) O(n3)。
Code
费用流(好烦啊…),建立源点 S S S和汇点 T T T,一个点向下一个点连接两种边,一种为流量为1,费用为标本价值的边,另一种是流量为无穷大,费用为0的边。 S S S向出发点连接流量为该点出发机器人个数,边权为0的边,结束点向 T T T连接流量为该点结束机器人个数,边权为0的边,求最大费用最大流。时间复杂度为 O ( ( P Q ) 3 ) O((PQ)^3) O((PQ)3)。
Code
接着费用流,其实是最大权不相交路径问题。离散化所有端点,建立源点 S S S和汇点 T T T,S向1点连接流量为 k k k,边权为0的边,然后每个点向下一个点连接流量为无穷大,费用为0的边。对于每个线段,线段左端点向右端点连接流量为1,边权为线段长的边。最后的一个端点向 T T T连接流量为 k k k,费用为0的边,跑最大费用最大流即可。时间复杂度 O ( n ( m + n ) 2 ) O(n(m+n)^2) O(n(m+n)2)。
Code
Byvoid:这题和上一题一样。
其实是一样的……
注意斜率不存在的线段和直线重合,认为直线与线段有一个交点。
所以像上一题一样区间覆盖即可。注意斜率不存在的直线的处理方式,可以将左端点坐标减去 0.5 0.5 0.5 再进行计算。
当然实现的时候是乘 2 2 2 减 1 1 1。
Code
费用流,对于一个位置拆成两个点 x , y x,y x,y,对于一个位置 i i i,如果这个位置是平地,则 i . x i.x i.x向 i . y i.y i.y连费用为0,流量为无穷大的边,如果这个位置为石块,再多连一条费用为1,流量为1的边,如果这个点为障碍,则这两个点之间连边。对于每一个点, i . y i.y i.y向 j . x j.x j.x连流量为无穷大,费用为0的边,建立源点 S S S和汇点 T T T, S S S向 ( 1 , 1 ) (1,1) (1,1)点连接流量为 k k k,费用为0的边, ( Q , P ) (Q,P) (Q,P)向 T T T连接流量为无穷大,费用为0的边。跑最大费用最大流。所有满流边构成多条满流路径,每条从S到T的路径就是一个探测车的路径。时间复杂度大概为 O ( ( P Q ) 3 ) O((PQ)^3) O((PQ)3)。本题有SPJ。
Code
类似于方格取数问题,先将棋盘黑白染色,题目中图片显示如果一个格子放了骑士,那么不能放骑士的格子颜色与这个格子不同。于是建立源点 S S S和汇点 T T T, S S S向白点(图片中黄点)连接流量为1的边,然后白点向不能走的黑点连流量为1的边,最后所有黑点向 T T T连流量为1的边。这里出现的白点和黑点均需没有障碍。然后求个 S S S到 T T T的最大流,答案为所有可用的格子数减最大流。时间复杂度 O ( n 4 e ) O(n^4e) O(n4e)
Code