集训队论文阅读笔记-姜志豪-网络流的一些建模方法
最大流建模
Luogu-P4311 士兵占领
写一下自己的办法。
考虑一个类似的问题”一行最多 (l_i) 个士兵,一列最多 (c_i) 个士兵,求最多放多少个士兵“。这个问题可以通过一行一个点,一列一个点,如果位置 (a_{i,j}) 可以放人,就将 (i) 行与 (j) 列之间连边。
那么如何解决原问题?考虑原问题等价于每个位置上已经有 (x) 个兵,现在要去掉一些兵,但剩下的每行每列的总兵数有下线,求最后剩下的兵数最小多少个。所以限制等价于去掉的兵的数量有上限,就可以用上面说的问题求解了。
Dining
其实这题可以推广的。
如果推广成 1 只奶牛对应 3 个方面的东西,我不会做。
但是如果推广成两种奶牛,第一种奶牛需要A和B两种方面的东西,第二种奶牛需要B和C两种方面的东西,两只奶牛可以呆在一块当且仅当:这两只奶牛属于不同种,并且喜好的 B 东西一样。求最多多少对奶牛呆在一块并且三种东西都能满足他们的需求。
做法:可以考虑如下建图:东西 -> 奶牛 -> 东西 -> 奶牛 -> 东西(与奶牛相邻的是他喜欢的东西)。
Collector’s Problem
Friend 可以做的只是将 Bob 已有的卡片换成别的卡片。
考虑如下建图:
- 每个卡片、人都有一个节点
- 如果 Friend 没有卡片 a ,那么卡片 a 向 Friend 连一条边。表示别人可以给 Friend 卡片 a 。
- 如果 Friend 有至少两张卡片 a ,那么 Friend 向卡片 a 连边。表示 Friend 可以给别人卡片 a 。
- 起点向所有 Bob 有的卡片连一条容量为 Bob 这张卡片的数量。
- 每张卡片向终点连一条容量为 1 的边。
最大流即为答案。
最小割建模
用容量为正无穷的边表示冲突
【NOI 2006】 最大获利
这题很有迷惑性。这里一个用户依赖两个站点,所以很容易就想用一条边表示用户。然而这样并不能走通。
就当成一个用户依赖两个站点就好了。答案就是 利润之和 (-) 得不到的利润 (-) 成本。也就是得不到的利润 (+) 成本最小即可。
这样考虑最小割建图:
- 一个用户代表一个点
- 一个站点代表一个点
- 用户向两个依赖的点连边,边权为正无穷
- 起点向用户连边,边权为用户付的钱
- 站点向终点连边,边权为修建站点的代价
那么一个路径,S->用户->站点->T 中 S->用户 与 站点->T 之中必然有一个要割掉。
【Codechef Dec14】 Course Selection
这就比较巧妙了。还是最小割建图。
建图要分部建图。先建出满足某些条件的,再不断完善。
将最大得分转化为最小扣分(也就是 (s_{i,j}) 表示 (100-x_{i,j}) ,让所有课程的 (s_{i,j}) 和最大)。考虑建出不满足先后顺序的图,再在这基础上改进。
可以考虑这样:
- ((i,j)) 向 ((i+1,j)) 连边,其中 ((i,j)) 表示第 (i) 学期学习第 (j) 个科目。(s) 向 ((i,1)) 连边,边权为 (s_{i,j}) 。
- 割掉 (s_{i,j}) 表示选择了 (i) 这个学期上 (j) 这门课。
那么如何满足先后顺序呢?
可以考虑这样:
- (a) 课程在 (b) 之前上,那么对于所有 ((i,a)) ,向 ((i+1,b)) 连边。
- 对于存在 (a) 课程在 (b) 之前上,那么 (s) 向 ((i,b)) 连一条容量为 inf 的边。
从两点关系的角度进行最小割建模
happiness
要点:
- 这样的建图结构,如果 (x) 与 (y) 最终不连通(也就选择是 (x) 保留 (a) ,(y) 保留 (d)),则需要割掉边 (e) 。
这题好像和文理分科还不太一样。。
考虑一个点代表一个人,如果保留和 (s) 的连边,就代表选择了文科,如果保留和 (t) 的连边,就代表选择了理科。
考虑一对好朋友 (x) 和 (y) 。
如果 (x) 和 (y) 都选了文科,那么需要增加喜悦值。也就相当于,选的科目不一样就减少喜悦值。
所以考虑 (x) 和 (y) 之间连接一条边,权值为选择不同科目减少的值。这样如果保留了 (x) 与 (s) 的边,(y) 与 (t) 的边,中间这条边就必须删掉。
Google Code Jam 2008 Final E, The Year of Code Jam
要点:
- 黑白染色(只可意会不可言传)
- 最小割连边不一定是有向的,仔细体会有向边的作用。
这个题其实大部分和上一道题一样,区别在于如果相同则减收益,上一道题是如果不同则减收益。就是将上一道题反过来了。
那么考虑黑白染色:
- 黑色点:
- 与 (s) 相连打比赛
- 与 (t) 相连不打
- 白色点:
- 与 (s) 相连不打比赛
- 与 (t) 相连打比赛
照样一个点与相邻的点连边,表示额外损失。
这样会发现,如果黑色点与 (s) 连边,他相邻的白色点与 (t) 连边,那么就意味着这两天都选择了打比赛,就意味着中间那条边会被割掉。
但是如果这样,都选择了不打比赛,中间那条边也会被割掉。这样就不对了。所以考虑将中间那条边设为有向边,具体的,就是让黑色点连向白色点。这样再都选择不打比赛时不割中间那条边也不存在一条通路。
费用流
【BZOJ 1283】序列
要点:
- 将 ”一个区间最多选择 (k) 个“ 视作 ”选 (k) 次,一次一个区间只能选择一个“
- 不一定非得源点向每一个序列上的点连边,可以顺着连。
错误:
- 我开始以为这样建图是可行的:
- (s) 向序列的每一个数连边,流量为 (1),费用为 (a_i) 。
- 用一个点代表一个长度为 (m) 的区间,向终点连流量为 (k) ,费用为 (0) 的边。
- 每个数向他所属的长度为 (m) 的区间连边,流量为 (1) ,费用为 (0) 。
- 但实际上是不对的,因为这样一个数 (a_i) 的流量可以流向其中任何一个包含它的区间,并不是所有被长度为 (m) 的区间包含的数的流量都流到了这个区间到终点的边上,所以可能导致一个区间不止有 (k) 个数。
题解鸽了。
【WC2007】剪刀石头布
要点:
- 在一条边的流量会不断变化的时候,考虑将这条边拆成好几条边(权值要递增,即前 (i) 条边的权值之和恰好是第 (i) 种变化的权值)
- 正难则反(计数中,总数减去不符合条件的)主要要想到这样做,怎么做倒是不难。
记得写清楚为什么这样统计三元环的总数量是正确的(关键在于没有少减掉东西)。
流量平衡
鸽了。