网络流复习

放一些我做过的网络流

P1231 教辅的组成

每个物品被选多少次均由他们所连的边限制,但是从 \(S\) 出发的边和从 \(T\) 出发的边只能约束两种点,另外一种点拆成两个,加一条 \(x \to x'\) 的流量为 1 的边即可

P1251 餐巾计划问题

看到数据很小,且 \(DP\) 很难记录状态的题大概就是网络流量了,可以用网络流想一下

首相考虑费用流的特性,流量会流满,利用这一点,我们可以满足每天需要的餐巾纸都能被提供

考虑餐巾纸用过后会变成脏餐巾纸,利用流量的特性将没洗的留给第二天,但是这有出现了一个问题,每天,既用卫生纸,又产生脏卫生纸,这两种纸肯定不能和在一起,而且如果设用纸巾是用掉流量的话,就需要 \(S\) 再连入额外的流量

这时一个点已经无法处理了,因为每天用多少纸是固定的,所以将一个点拆成两个,早上和晚上,早上用纸,晚上产生纸和处理洗纸,对应到图上是这样的

  • 一个点分成早上和晚上 \(x, x'\)
  • 每天可以购买新纸,\(S \to x\)
  • 必需要用纸 \(x \to T\)
  • 产生脏纸 \(S \to x'\)
  • 脏纸留给明天 \(x' \to (x+1)'\)
  • 清洗脏纸 \(x' \to (x + a)\)

P1345 [USACO5.4]奶牛的电信Telecowmunication

求最小的割点数

将点拆成两个点,加入额外的边来约束,\(x \to x'\) 流量为 1 的边

  • 最大流等于最小割

证明

考虑跑完最大流的图,无法找到从 \(S\)\(T\) 通路,也就是说图被满流的边分成了两部分,连接两个部分的边就是最小割,且他们的权值加起来就是最大流

从最小割的角度来看,一但割去的边 \(<\) 最大流,那一定可以找到 \(S\)\(T\) 的通路

P2050 [NOI2012]美食节

首先所有菜要被做完,那对于每种菜分配它个数个流量

发现一个同学需要等待的时间仅和他选择的厨师第几个做他的菜有关,考虑将厨师第几次做菜拆成点

如果厨师是倒数第 \(k\) 个做,则有 \(k a[i][j]\) 个代价被等待后 \(k\) 个菜的同学贡献

本身费用流这种算法就有浓重的贪心(最短路)气息,我们可以根据它贪心(最短路)的特性,进行一些边数上的优化

考虑一个厨师,如果倒数第一道菜没被做的话,一定不会做倒数第二道

因为第一道菜的边权最小,从最短路的角度考虑一定会选它

每次都在最后一道菜被选后再连其他的边,就可以优化了

P2057 [SHOI2007]善意的投票 / [JLOI2010]冠军调查

考虑最小割数学形式

考虑一个点在 \(S\) 集合里是 0 在 \(T\) 集合里是 1

那么一个点是 1 时,它只有在零里才有贡献连边 \(x \to T\) 否则连边 \(S \to x\)

当两个点时朋友时,他们在不同的集合里才会有贡献,连边 \(x \to y\), \(y \to x\)

P2472 [SCOI2007]蜥蜴

主要问题是每个石柱能站的次数有限,那石柱就对应一条边,走 \(a\) 次对应流量为 \(a\)

P2598 [ZJOI2009]狼和羊的故事

既可以是一眼题又可以是有些东西的题

一眼就可以看出来,要用最小割把狼和羊分开,那 \(S\) 向狼连 \(inf\),羊向 \(T\)\(inf\),每个点向周围连 1,考虑割掉的边是栅栏

之所以说它有些东西,是应为它可以表示成数学形式,考虑将狼划分成 0 集合,将羊划分成 1 集合,没有归属的点随便

如果两个点不在同一个集合,那么它需要栅栏分开,就是每个点向周围连 1 的边,由此可知,0 的归属就不需要讨论了

P2764 最小路径覆盖问题

每个点至多被一条路径覆盖,考虑网络流中约束是边

每个点拆成两个点 \((x, x')\) ,可以向自己连向的点做匹配 \((x' \to y)\),考虑一开始是 \(n\) 条路径,每匹配一个点就减少一条路径

答案就是 \(n\) - 最大匹配数

P2765 魔术球问题

每个数可以放在和它和是平方的数上面

我们可以想到,如果一个点可以放在某个点上面是那个点向它连边

如果一个点向它所有能连的点连边,那么它的最小链覆盖就是我们要找的答案

经过简单推理可以发现,每个点可以连接的点的大小是递增的,那么把编号小的点放在柱子下面一定更优

这样连边就行了

P2766 最长不下降子序列问题

通俗的,对于每个数只能取一次和取无限次,将点拆开加入边约束

因为让求最长上升子序列的个数,所以当一个数字被选择时,它必须是最长上升子序列的一部分

我们求出最长上升子序列的 \(DP\) 数组,当 \(x\) 可以连边 \(y\) 当且仅当 \(y\)\(DP\) 中可以从 \(x\) 转移过来

这样问题就显然了,我们只需要求解 \(DAG\) 上的最长链个数即可

具体的连边方法,设最长上升子序列长度为 \(k\)

  • 每个 \(x\)\(x'\) 连边

  • \(f_x = k\) 时,从 \(S\)\(x\) 连边

  • \(x < y\)\(f_x + 1 = f_y\)\(v_x < v_y\) 时, \(y'\)\(x\) 连边

  • \(f_x = 1时,\)x'$ 向 \(T\) 连边

posted @ 2020-06-12 21:57  __int256  阅读(165)  评论(0编辑  收藏  举报