集训队论文阅读笔记-姜志豪-网络流的一些建模方法
最大流建模
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
要点:
这题好像和文理分科还不太一样。。
考虑一个点代表一个人,如果保留和 \(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\) 种变化的权值)
- 正难则反(计数中,总数减去不符合条件的)主要要想到这样做,怎么做倒是不难。
记得写清楚为什么这样统计三元环的总数量是正确的(关键在于没有少减掉东西)。
流量平衡
鸽了。