• 深入浅出网络流


    最小割

    最大权闭合子图

    闭合子图是什么?

    就是一个有向无环连通图

    最大权闭合子图就是说,图上的节点有正有负,我们要选出权值最大的点集。

    建图过程:

    1. (Sxrightarrow{w(i)} i (w(i)>0))
    2. (ixrightarrow{infty} j ((i,j)in E))
    3. (ixrightarrow{-w(i)}T (w(i)<0))

    然后跑最大流,用(sum w(i) (w(i)>0))所有正权点的权值和)减去求出来的最大流(最小割)就是答案。

    为什么要这样呢?

    分类讨论:

    1. 如果正权边被割了,那就说明在最小割中,正权边(leqslant)对面的负权边(否则被割掉的就不会是正权边而是负权边),对应的情况就是:选了正权边之后,正权边所连通的负权边比正权边还大(在绝对值上),这样选就亏本了,所以才需要割掉(在代码中就是从正权点的权值和中减去)。
    2. 如果负权边被割了,就说明正权边比负权边大,选了之后不会亏本,割掉的只是选了这个正权点所付出的最小成本。

    (感觉这个是最小割当中最好理解的了……)


    8.6 老师提了一个挺有意思的模型:

    有若干个活动,分别需要一些房子。使用房子有两种方式:

    1. 每个活动分别租一间
    2. 直接买一间,这样每个活动都能使用,不需要再额外租。

    就是说,一个负权点的代价可以有不止一种形式。

    1.png

    这样的话,原本那些连接正权点和负权点的,容量为(infty)的边就有用了:


    二选一模型

    就是,一个节点有两种代价(或者收益),还有一些限制,让你找出最小的代价(最大的收益)

    如果没有其他限制的话很简单:将两种代价(或者收益)一种连向(S),另一种连向(T),然后求出最小割,最小割就是最小的代价(如果是收益的话,就是必须要舍弃的最小收益)。

    1. 如果(a)被割给了(S)(b)被割给了(T),就有相应的代价;(双核CPU善意的投票
    2. 如果一个点集被割给了(S),就有相应的收益;(寿司餐厅Happiness小M的作物
    3. 如果一个点被割给了(S),并且一个点集(V')中有一个点被割给了(T),就有相应的代价

    第一种

    [Sxrightarrow{w(a)} a xrightarrow{ ext{代价}}b xrightarrow{w'(b)}T ]

    这样的话,求出最小割之后,割掉的就是最小的代价。

    当然,像善意的投票就只需要根据意愿在(S)(T)之间二选一即可(代价还是照样连)

    第二种

    代价是用来最小化的,所以用最小割可以直接解决,那收益呢?

    没关系,可以先把收益都加起来,然后再把收益当成代价去建弧,跑最小割。

    这样,割掉的就是最小的收益,剩下的收益自然就是最大的了。

    第三种

    (记不得老师讲什么了,自己脑补的)

    [Txleftarrow{w(a)} a xleftarrow{代价} x(附加点) xleftarrow{infty}(vin V')xleftarrow{w(v)} S ]

    (画反了,不想调)

    (因为例题少所以就不讲了,反正最小割目前只接触了这两种模型)


    二分图

    (mathrm{DAG})最小路径覆盖

    ↑字面意思:用最少的路径(不是连接两个节点的)覆盖(mathrm{DAG})上所有的点(两条路径不能经过相同的点)。

    魔术球问题

    可以发现,如果把能够组合成完全平方数的数对连边,就会形成一个或以上的独立的(mathrm{DAG})

    那问题就转化成了(mathrm{DAG})上的最小路径覆盖

    首先,因为对于一个数,有两种流量流入:一种是其他(比它小的)数想要和它组成完全平方数;另一种是它自己要和比它大的数组成完全平方数

    所以我们要将一个“数”拆成两个点:一个给比它小的点去连,另一个给它自己去连别人。

    连边的话,将小数的点的入点连向大数的点的出点(前提是小数和大数的和是完全平方数),源点连向每个入点,每个出点连向汇点。

    然后每次加入新数就连上相应的弧(比如将前面能够组成完全平方数的出点入点连弧),再在先前的残量网络上直接跑最大流,如果最大流没有增加,说明这个数不能与之前的所有数组成完全平方数,就把柱子的数量加一即可。


    事实上,一般的最小路径覆盖也是差不多和上面一样的,但如果要你直接输出最小路径数的话

    就输出((N-最大流))就可以了。(这个不难理解吧)

    最小点覆盖 & 最大独立集

    先来一波定义

    点覆盖:G任意边至少有一个顶点属于源点(s)的点集(S)

    独立集:G中两两互不相连的点集(S)

    最小点(权)覆盖:(点数/点权)最小的点覆盖;

    最大点(权)独立集:(点数/点权)最大的点独立集。

    最大流=最小割=最小点覆盖=(N-最大独立集)

    上面很容易证:因为是最小割,所以只要把割边所连上的点删除,那么就能用最小的代价(s)(t)隔离开来。

    可能还可以删掉其它的点(比如说你可以把和源点(s)直接相连的所有点都删掉,点集(S)就是与(s)直接相连的所有点),但是这样都没有最小割优。

    然后,引入了一个点覆盖,就说明有一对点必须二选一,所以最大独立集就要(-1),因为点与点之间互不相连


    如果是普通的最小点覆盖的话,容量设为(1)即可(当然,中间二分图的弧的容量还是(infty))。

    如果是最小点覆盖的话,把容量设为权值即可。


    最后补充一个:二分图最大权匹配

    按照费用流跑即可(应该要把费用取为负数再跑)

  • 相关阅读:
    哈密顿环求解 C++实现 回溯法
    哈密顿环求解 C++实现 回溯法
    哈密顿环求解 C++实现 回溯法
    图着色问题 配色方案 C++实现 回溯法
    图着色问题 配色方案 C++实现 回溯法
    图着色问题 配色方案 C++实现 回溯法
    图着色问题 配色方案 C++实现 回溯法
    n-皇后问题 C++实现 回溯法
    n-皇后问题 C++实现 回溯法
    如何给Sqlite添加复合主键
  • 原文地址:https://www.cnblogs.com/info---tion/p/11305399.html
Copyright © 2020-2023  润新知