网络流拓展二
POJ 3680(区间k覆盖问题+离散)
题目要求
枢轴上有一些带权值的区间 选出权和尽量大的一些区间 使得任意一个数最多被k个区间覆盖
参考AC代码
|
|
思路
MCMF解法:
把所有点排序后离散化去重
相邻点加边 容量为k 费用为0
对于原来的区间[l,r] 找到排序后l和r的位置建边 容量为1 费用为-w
源点到点1建边 容量为k 费用为0 满足最多k区间覆盖
点mm到汇点建边 容量为k 费用为0
跑一遍MCMF 答案取反就是所求(求的是最大 MCMF是最小费用)
HDU 4106(区间k覆盖变形)
题目要求
一共有n个水果 每个水果有一个权值 在连续m个水果中最多只能划k个 问所能划到的最大权值
参考AC代码
|
|
思路
POJ3680是区间内对点的限制 而本题是点对区间的限制 所以把区间变点 点代表区间
在n个点里面一共有n-m+1个长度为m的区间,现在把这n-m+1个区间两两之间用点隔开,那么一共用n-m+2个点
如果选n这个点则从点max(1,i-m+1)到点min(fin-1,i)+1之间的区间每个点(此点代表的是线段)可选的点数就会减一
除此之外其余的建边与上题一样 加剪枝防tle
POJ 3762(同3680)
题目要求
给出n个任务 每个任务给出一天内的时间间隔以及完成的分数
给出k天时间 问能获得的最大分数
参考AC代码
|
|
思路
同3680
每个时刻最多重叠k次(k天)
注意本题输入最好用scanf 用scanf不能取消流的限制
POJ 3422(区间累计k覆盖最大值)
题目要求
N*N的地图上每格都有分数,分数只能获取一次。有人从左上方开始,每次向右或下移动一格,到右下方为止,记为一次环游。问第K次环游后累计分数的最大值
参考AC代码
|
|
思路
可以为每个点创建伪点,由两条有向边相连。原始点到伪点连一条容量为1,权值为负分数的边;原始点到伪点连一条容量为k,权值为0的边。
前者表示分数只能拿一次,后者表示第二次第三次……可以继续走这个点,但是不拿分数。
多源多汇问题 建一个超级源点连向(1,1)位置 建一个超级汇点与(n,n)相连 流量为k 费用为0
u连向v代表拆点的部分 v连向u代表向下和向右的过程
HDU 3667(费用与流量平方)
题目要求
容量c均为整数 并且每条弧还有一个费用系数a 表示该弧流量为x时费用为ax²
问流量是否可以满足k 若满足输出最小费用那个 不满足输出-1
参考AC代码
|
|
思路
蓝书P366
拆边 容量为c 就把u-v拆成c条边 每条变容量为1 费用为a 3a 5a···
跑MCMF即可
本题需要注意多了一个是否满足k流 所以需要判断flow==k时输出mincost 否则不满足k流直接输出-1
S=0 与点1额外建边容量为k 费用为0 把流量限制在k之内 防止重边的干扰
UVA 11613(流量不固定s-t最小费用流)
题目要求
给出m个月 每个月可以生产make_limit个产品 成本为make_cost 该月售价为price 最多售出sell_price件
每个产品可以封存max_store月 每个产品每个月封存需要花store_cost的钱
问这m个月能获得的最大利润是多少
参考AC代码
|
|
思路
蓝书P367
费用有正有负
在最短增广路费用为正时停止增光
流量不固定 BF里不需要flow参数 开LL
建超级源点和超级汇点 建图 月份和月份之间保存封存的费用
LA 3231(公平分配问题)
题目要求
把m个任务分配给n个处理器 其中每个任务有两个候选处理器 可任选一个分配 要求所有处理器中 任务数最多的那个处理器所分配的任务数
尽量少 不同任务的候选处理器集保证不同
参考AC代码
|
|
思路
二分网络流
蓝书P367
ZOJ 2587(最小割唯一判断)
题目要求
给出一张无向网络图,并给出起点和终点,破坏图的每一条边需要一定的费用,问破坏起点和终点的连通性的费用是否唯一.
参考AC代码
|
|
思路
破坏两点的连通性的最小费用,很容易联想到 网络流中的最小割,
建立源点 汇点 同时 因为图是无向图,我们需要将每条边建两次(正反向) 也可以直接把反向容量设为cap
然后就是判断这个最小割是否唯一了:
首先 从源点开始 dfs 通过非饱和边 统计所有能走到的点 记为s1
然后 从汇点开始 dfs 通过非饱和边 统计所有能走到的点 记为s2
如果s1+s2==n则说明最小割唯一
UVA 11248(扩弧)
题目要求
给定一个有向网络 每条变均有一个容量 问是否存在一个从点1到点N 流量为C的流 如果不存在 是否可以恰好修改一条弧的容量 使得存在这样的流
蓝书P368
参考AC代码
|
|
思路
先跑一次最大流,最大流如果大于等于C,就不用括弧了
如果不行的话,就进行括弧。
扩大哪些弧的容量呢。答案是割边的容量,因为最小割==最大流
我们先找出所有的割边,如何找割边呢,如果是dinic算法的话,就找到vis[u] == true 而vis[v] == false 且该边容量大于0的边,这些边就是割边了
接着将割边一条一条的扩容,只需要扩大到C的容量就可以了,然后在残余网络上跑最大流就可以了
还有一个问题是怎么求残余网络,只需要将所有边的容量减去流量就是残余网络了
加上2个优化:第一个优化是求完最大流后把流量留着 以后每次在它的基础上增广
第二个优化是每次没必要求出最大流 增广到流量至少为C时就停下来
LA 2957
题目要求
宇宙中有n个星球 你的任务是用最短的时间把k个超级计算机从星球S运送到星球T 每个超级计算机需要一整艘飞船来运输
行星之间有m条双向隧道 每条隧道需要一天时间来通过 且不能有两艘飞船同时使用同一条隧道 隧道不会连接两个相同的
行星 且每一对行星之间最多只有一条隧道
蓝书P368
参考AC代码
|
|
思路
蓝书P368
注意点:
第一天的点编号为0->n-1
对于i+1天 清空后与第i天建边
为满足流恰好等于k 每次在原有最大流的基础上增广 设置一个limit=k-flow 每次增广剩下的流量
对于Maxflow函数中 同样为确保流量尽可能等于limit又不超过limit 每次增广limit-flow的流量
对于输出解 idx初始值=2*n是为了跳过原地不动的点 对于每个u[i]和v[i] 其实建边了四次 正向2次 反向2次
所以idx+2实际上是判断u[i]->v[i]和v[i]->u[i]的流量 如果前驱flow==1后驱flow==0 存入a和b 反向同理
最后对于每一天遍历满足条件a边的大小和k个计算机 如果该计算机未走动过(move[j]==0)并且此时它的位置在a[i]处 存入pi排序输出
LA 2531
题目要求
有n支队伍进行比赛 每支队伍需要打的比赛数目相同 每场比赛恰好有一支队伍胜 另一只队伍负 给出每支队伍目前胜的场数和败的场数 以及
每两个队伍还剩下的比赛场数 确定所有可能得冠军的球队(获胜场数最多的得冠军 可以并列)
蓝书P369
参考AC代码
|
|
思路
见注释
蓝书P369