Codeforces - tag::flows 大合集 [完坑 x14]

589F

题意:给出n个时间区间,每个区间挑定长的非连续区间,求不同个区间不存在时间冲突的最大定长,输出乘上n

二分图模型+二分长度,左顶点集为区间编号,右顶点集为时间编号(1...10000),汇点到左顶点集的容量为枚举长度,右顶点集到汇点的容量为1,左到右顶点集的容量如果符合条件则连边且置1,注意左闭右开

判断只需直到是否满流即可

https://paste.ubuntu.com/p/JBDQ49k9yv/


321B

题意:你有m张卡牌,对方有n张卡牌,卡牌类型有攻击和防御两种类型,而你只有攻击卡牌
卡牌的具体规则如下:
每张卡牌只需使用一次
攻击类卡牌值为x,则可以攻击对方,
若对方无卡牌,则受到x伤害;
若对方有攻击类卡牌且值y<=x,则受到x-y伤害,同时该卡牌作废
若对方有防御类卡牌且值y<x,则对方不受伤害,同时改卡牌作废
否则该攻击卡牌无法使用

现在是我方的回合,求使对方造成最大伤害的值(即使卡牌没用完也可以随时停止攻击)

这是一个二维问题,一个维度是卡牌数量(流量)另一维度是伤害值(费用),因此使用费用流求解

对我方m个点编号1...m,对方n个点拆成两个(非必要),编号m+1...m+n,m+n+1...m+n+n,源点s,副源点ss,汇点t

\(s->ss,(flow,0)\)
\(ss->[1...m],(1,0)\)
\([m+1...m+n]->[m+n+1,m+n+n],(1,-2inf)\)
\([m+n+1,m+n+n]->t,(1,0)\)
\([1...m]->[m+1...m+n]\),若对方卡牌为攻击型且符合限制,\((1,inf-(x-y))\),若为防御性且合法,\((1,inf)\)

这样保证了每条\(s->t\)的边的花费形式为\(-(inf+val)\),既最大流下总花费为\(\sum(-val-inf)\),最后把得知的项数乘上inf再取反就是枚举使用卡牌数的答案

但这样并不能保证一种情况,敌方的卡牌耗完了,我方还有卡牌剩下,此时无法表示剩余的伤害

因此要额外加边\([1...m]->[t],(1,inf-x)\),此时单边的流量是\(inf-x\)的形式,在inf足够大的情况下是不会优先跑这些表示剩余的边(其它边保证为负权)

因此最终形式是\(\sum_{i}(-inf-val_i)+\sum_{j}(inf-val_j)\)

得出结果后分别统计两种情况的inf并修正取反便是答案

https://paste.ubuntu.com/p/k2HZJmsQwQ/


498C/499E

题意:给出\(a[1...n]\)和m对下标\(pair(i_k,j_k)\),其中\(i_k+j_k\)必然是奇数,每次操作可以任选一对pair下标的元素,对其整除任意一个数(大于1),并替代回原来位于\(i_k,j_k\)的数,问最多能操作多少次

对于\(a[i_k]\)\(a[j_k]\),能整除且尽量多次数的必然取gcd的质因子来除,否则取合数不划算

对于\(i_k+j_k==odd\),其中一个必然是奇数另外一个是偶数,可以联想到奇偶二分图模型

对于\(a[1...n]\)中的所有质因子,其答案的贡献是相互独立的(这一点我当时没看出来)

因此可以构造\(O(nlog10^9)\)个关于质因子的二分图模型,依次跑最大流,每次枚举完把\(a[1...n]\)的当前枚举因子全部筛除

最大流的左顶点集设为奇数下标,右顶点集则为偶数,两边取inf,左右对于源点汇点分别取该下标下元素的当前枚举质因子的个数

https://paste.ubuntu.com/p/g4mwBdC7nt/


727D(水)

题意:简单匹配,输出方案

这都配当D题

https://paste.ubuntu.com/p/rjVpbZBJ4T/


316C2

题意:给定n*m网格,每个网格有一种编号,每个编号出现的频率必然是2,定义编号相邻的两个相同的编号所在的网格有一个边重合,求最少的编号对数转换次数使得所有编号相邻

编号必然有n*m/2种

如果某个编号存在不相邻的情况,要么自己要转移,要么相邻的不相等编号要转移

那么由此得是一种棋盘模型,要求代价为最小费用

对网格进行黑白分组,黑组连向源点,白组连向汇点,每条边容量为1,费用为0,此时两个点集相互独立

联系两个点集,对黑组的每一个网格的四个方向连边,如果是相同编号,则无需代价,表示可以直接匹配,否则费用为1,表示总有一方需要移动

那么跑mcmf的结果就是总是满足全部匹配下的最小代价

https://paste.ubuntu.com/p/hQtnzyTKrQ/


169C

题意:n个带时间区间和不同价值的任务和k个机器人,每个机器人可接所有不相交的区间的任务,求最大价值

一开始很自然的想到左子集为时间开端st,右子集为时间终点ed,两端接流量1费用-c的边,末端暴力在接上大于自身的其它开端,然后源点汇点限制流量

然而我低估了mcmf的复杂度,总之暴力构图是不可取的

摸了qsc的题解

对所有时间离散化并标号,假设有cnt个时间点,就构造除了汇点的cnt+1个点直接相连(1为源点),容量均为k,费用为0

然后遍历n个时间区间,从hash[a[i].st]到hash[a[i].ed]+1建一条(1,-c)的边,表示随时可往这里出发(其它边容量均为k)且不允许相交(下一步为离散值ed+1的地方开始),cnt+1防止最后+1超过编号范围

https://paste.ubuntu.com/p/9gvdkC6XXj/


739E

题意:你有a个大师球和b个大师球(改),共有n只pokemon,每只pokemon被抓的概率分别是p_i和q_i,每种类型的大师球不能重复用于同一只pokemon,但两种球可以同时用,求能抓到最多的pokemon的期望个数

如果没有同时使用的条件,只需简单二分图跑浮点mcmf

其中一个技巧是最大流无法确认能否到达a+b的情况下把连向汇点的边的容量加大且合法即可

考虑同时用两种球被抓的概率为\(1-(1-p)*(1-q)=p+q-p*q\),对比没有同时使用的条件多了\(-p*q\)

改写方案1.左顶点集分为p_i和q_i的节点各自连向i,容量1费用p_i或q_i,然后p_i和q_i同时指向另一个中介节点x,两边的容量为1费用也是p_i和q_i,然后x指向i费用为p_iq_i,i后连向汇点t且容量为1

这样似乎无法保证最大流的前提

改写方案2.左顶点集分为p_i和q_i的节点各自连向i,容量1费用p_i或q_i,i后连向汇点t,但分为两条边,一条(1,0),另一条(1,-pq),由优先度可得这样就能满足最大流下的最优解(实际操作需取反)

注意是浮点运算

https://paste.ubuntu.com/p/bwsVqNjdvn/


863F

题意:给出n个不确定大小但可框定范围的数,求一种方案使得各个值的出现频率的平方之和最小

带平方权的费用流在刘汝佳的书里提过,只需1,3,5,7这样构造下去就好,扩展到其它情况只需算出作差的通项即可

别的没啥特别注意的

https://paste.ubuntu.com/p/hmGXK9HHcB/


717G

题意:给出一个string,其中每个位置有使用限制至多k次,给出一堆word和价值,表示每匹配一个word就能得到这么多价值,求区间覆盖的最大价值

本题和169C做法是几乎一样的,是一个区间k覆盖问题

把离散的时间点相连,容量为k,保证覆盖至多k次

对于n个word的每个可行区间的左闭右开端点连接一条(1,-p)的边,防止lo=hi

https://paste.ubuntu.com/p/b5pFyYv8YS/


847J

题意:给出n个学生和p对关系,每队关系的人中必须有一人给另外一个人送礼物,这种规则下肯定会有最惨的那些人(送出礼物最多),求最惨情况下的最少送出礼物的个数

二分最惨的答案(??)

我们首先能看出来的是总共送出了p份礼物,我们设它为合法的最大流

然后每个人都可能是最惨的,应该由与他相关的关系节点的总数进行限制流量

源点\(S\)连向p个关系节点\(P_i\),容量为1

每个\(P_i\)连向两个已知关系的人\(u,v\),容量各为1

每个人\(u\)连向汇点\(T\),容量为枚举出的最惨可能\(x\)

然后二分判断是否满足最大流为p

注意每一次二分都要记录最大流的解,因为我的破板子最后一步存在直接越界的可能,所以不能在二分后再求解,这时的流可能无法得出结果

还要注意二分的上界\(hi\)要稍微设大一点,有可能第一步就直接越界然后也是不正确的

https://paste.ubuntu.com/p/KSGk9RWkb7/


808F

题意:给出n张卡牌,每张\(card_i\)卡牌有\(p_i,c_i,l_i\),表示当前卡牌的能力值为\(p_i\),编号为\(c_i\),至少使用等级为\(l_i\),
存在两种约束,若人的等级\(x<l_i\)则不能使用第\(i\)张牌,卡牌组合中不得存在一对卡牌使得\(c_i+c_j\)为素数
求在这些约束的前提下能达到最大能力的卡牌组合的等级下界

已知:
卡牌不互素 和 棋盘不相邻 的模型是一致的
求的其实是带权图的最大独立集

思路: 求二分图带权最大独立集 -> 求最小点权覆盖集

二分图的带权最大独立集:在一个二分图中,每个点都有一个权值,在保证选中的点不相交的情况下,求选出的点的最大权值和

放到棋盘上该问题就是网格不相连的前提下挑出最大权值的网格集合

用黑白染色二分图跑最小割

对于任意一个割集,与割相连的点都删掉就会得到一个独立点集(割边只能是源点到X,和Y到汇点的边)

也就是说跑出来的最大流是用最小的代价(损失)得到最大的带权点独立集

因此最后的答案就是所有点的权值和\(sum\)-最小割的容量\(cut\)

808F同理,只是不相邻的条件更换为和不为质数

按照奇偶构建二分图,如果\(isprime[u+v]==1\),则连一条容量无穷大的边
s到奇数连接数量 偶数到t同理

最小割为最小损失

目前比较难以相通的细节处理是对于1+1=2的特判处理

以下为一时臆测,不保证完全正确

因为两个1肯定能形成2,必须要割掉,那么就是说1的个数其实只保留1个就可以了,这个时候就不用割了,且\(sum_1-cut_1==sum_2-cut_2\),所以不会造成对答案贡献的影响,况且多出来的都是造成二分图矛盾的,不一定能保证最小割的正确性

那么还需考虑到底要保留权值多大的1?
首先可以得知的是无论权值多大的1在图中的结果如果被割的话都是\(sum_i-cut_i==sum_j-cut_j\),影响相同
但如果不被割的话显然选择权值越大的sum就会越大,cut无影响

综上可得就是贪心的选取权值最大的1即可

注意一下只有1的情况尽量特判(虽然似乎影响不大

https://paste.ubuntu.com/p/fr6g9pPJwc/


510E

题意:要求输出n只狐狸围在多张桌子上的方案,满足约束使得每相邻的两只狐狸的值为素数(已知值至少大于1)

和上一题有点类似,构造奇偶二分图

观察得每只狐狸两边都有狐狸满足和为素数,令奇数出度为2,偶数的入度为2,然后用流量表示度数跑最大流即可

https://paste.ubuntu.com/p/29ZTrf3QhQ/


311E

题意:有n个可以性转的大佬,给出初始性别和女装费用(转了就回不来),有m桩生意,每一桩指定某一集合内的大佬的性别(集合内性别一致),如果全部符合则给你w_i的费用,否则你拿不到,如果是特殊生意你还需要特意赔偿g块钱,求最多能赚多少

我觉这道题的建模挺刺激的...带集合的表示和赔偿的操作很巧妙

先把能得到的所有费用统计起来,然后最小割作为最小损失代价

对n个大佬进行黑白染色二分图,源点汇点分别连接且容量为性转费用
对m桩生意也进行黑白染色二分图,源点汇点分别连接且容量为w_i加上可能的g

以上都是可能存在的损失

考虑每一桩生意对大佬的影响,如果集合内的某大佬性别与初始设定不一致则连接一条inf的边,也既黑白相接,表示要么生意搞砸了要么不符合要求的都性转

再考虑每一桩生意对别的生意的影响,如果某对生意中存在相同的大佬但性别不一致,那肯定是冲突了,再连一条inf的边表示只能二选一

由此跑出的最大流就表示最小损失

注意边的方向啊(WA一发

https://paste.ubuntu.com/p/zpXHQPWxKW/


待做(不想做/做不动/沙雕题目说的啥意思):270E/723E/724E/362E/813D/280D/884F

不想做了orz

posted @ 2018-08-01 21:25  Caturra  阅读(184)  评论(0编辑  收藏  举报