首页 > 其他分享 >网络流与二分图的常见技巧

网络流与二分图的常见技巧

时间:2023-11-15 23:12:46浏览次数:40  
标签:二分 连边 匹配 技巧 覆盖 常见 最小 SCC

sto louis & Maverik orz!

写一些知识点,图论杂题过后单独开一篇。

最小割

最大流最小割定理

对于任意网络 \(G = (V, E)\) ,其上的最大流 \(f\) 和最小割 \(\{S, T\}\) 总是满足 \(|f| = ||S, T||\) 。
即,最大流在数值上等于最小割。

最小割的可行边与必须边

同一个网络的最小割有多种可行的方案,我们需要对一条割边的可行性与必要性进行讨论。
可行边: 指存在于任意可行割集中的的边。
必须边: 指存在于所有可行割集中的的边。

可行边

一条边 \(u\to v\) 作为最小割的可行边的充要条件是:

  • 这条边满流
  • \(SCC_u\neq SCC_v\)

第一条限制的必要性是显然的,我们来证明第二条限制。
\(u\) 和 \(v\) 不在同一强连通分量,等价于残量网络上不存在一条从 \(u\) 到 \(v\) 的路径。如果存在一条从 \(u\) 到 \(v\) 的路径,就会和 \(u\to v\) 满流后形成的反向边构成环,破坏了最大流的性质,\(u\to v\) 必然不能是可行边。

必须边

一条边 \(u\to v\) 作为必须边的充要条件是:

  • 首先它是一条可行边
  • \(SCC_s=SCC_u,SCC_v=SCC_t\)

后者等价于残量网络上同时存在 \(s\to u\) 和 \(v\to t\) 的路径。如果不存在,则说明只割掉前面(或后面)所有满流的边就能令 \(s\) 和 \(u\) 不连通(或 \(v\) 和 \(t\)),这样 \(u\to v\) 就不是必须要割的边。

最大权闭合子图

闭合图:一个有向图的子图,满足若一个点在该子图内,则它的所有后继节点都在该子图内。
最大权闭合子图:一个带点权的有向图,点权有正有负,求一个闭合子图的权值和的最大值。

做法

这是一个较为经典的问题。
考虑如下的建图:将点按照点权的正负分为正值点和负值点。源点向所有正值点连边,容量为点权;所有负值点向汇点连边,容量为点权的绝对值。在正负值点之间按照原图连边,容量为 \(\inf\)。

答案为正值点的权值和减去原图的最小割。

证明

考虑这样建边的实际意义,设 \(s\to i\) 的边不割表示选了这个正值点,\(i\to t\) 的边不割表示不选这个负值点。
那么 \(s\to t\) 连通就表示选了某个正值点但没选它后继的负值点,于是寄了。我们的目标是用最小的代价让它们不连通,这就是求最小割。
为什么不用反过来考虑呢?因为如果一个负值点被选,一定因为它是某个正值点的后继而不得不选。所以选的第一个点一定是正的。

CF311E Biologist

不会做 *2300 /oh。
首先完不成要倒扣的限制可以通过把达成条件的奖励加 \(g\) 来消去。然后对求的东西进行转化,最大化利润等价于最小化未获得的奖励+成本。
因此这样建图:

  • 若 \(S_i=0\),连边 \((i,t,v_i)\),割掉该边表示选 \(1\) 要花费 \(v_i\) 的代价;否则连边 \((s,i,v_i)\)。
  • 对每条限制开一个新点。如果限制是全为 \(1\),即限制某些位置不能有 \(0\),连边 \((s,j,w_j)\),\((j,x,\inf)\);否则连边 \((j,t,w_j)\),\((x,j,\inf)\)。如果割开限制边,则表明该奖励没有被达成。

这样建图可以保证一个点不会既满足 \(0\) 限制又满足 \(1\) 限制,因为这样这两个限制的边会通过这个点连通。

混合图的欧拉回路 Euler Circuit

与有向图、无向图的欧拉回路不同,在混合图中,我们需要对所有无向边进行合理的定向,使之转化为有向图求解。

先对所有边随机指定一个方向,令点的权值 \(d_i=in_i-out_i\)。我们希望通过调整边的方向,使所有 \(d_i=0\)。
考虑将原本 \(u\to v\) 的边反向,对 \(d\) 数组的影响是 \(d_u\gets d_u+2,d_v\gets d_v-2\)。因此我们把 \(d\) 数组全部除以 \(2\),一次反向操作的贡献变为 \(1\)。
对于 \(d_i>0\),连边 \((s,i,d_i)\);对于 \(d_i<0\),连边 \((i,t,-d_i)\)。对于原图的每条无向边 \(u\to v\),连边 \((u,v,1)\)。跑最大流,流满的边即为需要反向的边。

对所有边定向完毕后,跑有向图的欧拉回路即可。

费用流

那个长得神似 Dinic 的费用流其实叫 zkw 费用流。

[CQOI2012] 交换棋子

网络流题总是能写出层出不穷的假做法,怎么办呢。
忽略掉所有白棋子,那么问题相当于每次可以八连通移动,将黑棋子移动到指定的位置。次数限制在方格上,考虑拆点,连边 \((in_{x,y},out_{x,y},limit,0)\),\(limit\) 是交换次数限制的一半,特判下奇数且初始/终止为黑的点。
对于初始位置的黑棋子,连边 \((s,in_{x,y},1,0)\);对于终止位置的黑棋子,连边 \((out_{x,y},t,1,0)\)。每个格子向八连通位置连费用为 \(1\) 的边,表示交换,跑费用流。

然后这个假了,原因是要特判某个位置一开始就是黑的,最后还是黑的。这种情况不应当连边,因为它一直不动的话没有交换次数,不会贡献大小为 \(1\) 的流。

[NOI2012] 美食节

P2053 的加强版。这人怎么不仅不会网络流,还不会拆贡献 /cf
发现做每个菜的贡献跟前面做菜的总时间有关,试图倒过来考虑。设第 \(i\) 个菜是第 \(j\) 个厨师倒数第 \(k\) 个做的,它对答案的贡献是 \(T_{i,j}\times k\)。
至此,不同菜或厨师之间的贡献独立。比较暴力的做法是直接把每个厨师拆成 \(p\) 个点,分别表示这个人倒数第几次做菜,跑费用流,可以通过 P2053。

不过发现,我们只有先做了倒数第 \(i\) 个菜,才有可能做倒数第 \(i+1\) 个菜,否则一定不优。因此可以在 dinic 的过程中动态加边,每次增广后判断,等到倒数第 \(i\) 个已经被选,再连边第 \(i+1\) 个。这里要每次增广就判断一次,而不是全部增广完毕再加边。后者会使图中出现负环。

二分图匹配 & 偏序集

时间复杂度

匈牙利是 \(O(nm)\),Dinic 是 \(O(\sqrt{n}m)\)。

可行边与必须边

可行边:在图上满流,或 \(SCC_u=SCC_v\)。
必须边:在图上满流,且 \(SCC_u\neq SCC_v\)。

注意这里的条件与最小割的区别。

证明

假设我们已经得到了一组解。如果这个图上存在某条长度为偶数的交错路,把这条路上的所有边状态取反不改变答案。因此属于一条长度为偶数的交错路的匹配边均是可行边,且不是必须边。这等价于在残量网络中 \(SCC_u=SCC_v\)。

而必须边即为排除掉上述情况的可行边。

Kőnig 定理

最小点覆盖:选最少的点,满足每条边至少有一个端点被选。

二分图中,最小点覆盖 = 最大匹配。

解的构造

显然我们只要找到一种构造方式就证明了这个定理,因此下文仅叙述如何构造出一组合法解。
我们先求出当前二分图的最大匹配,并记录匹配边。

接下来,从右侧的所有非匹配点遵循如下规则开始 dfs,并标记所有经过的点:

  • 右部点只能通过非匹配边向左走;
  • 左部点只能匹配边向右走。

我们取左侧被访问过的点和右侧未被访问过的点,它们的并集为一个合法解。

证明

首先,右侧的非匹配点一定都被 dfs 到了,加入答案的一定是匹配点。
而右侧被 dfs 到的匹配点一定是因为与之匹配的左侧点被 dfs 到了,那么这条边的左端点已经被选入了最小点覆盖。
左侧的非匹配点一定不会被 dfs 到,否则我们可以让走向它的右部点与之匹配,不满足二分图最大匹配的性质。

那么我们得出结论:只有匹配边的端点会被选上,且每条匹配边的端点恰好被选了一个。

接下来证明这组解覆盖了所有的边。
只有出现左部点未被 dfs 到且右部点被 dfs 到的情况,才会两个端点都不被覆盖。根据是否是匹配边分讨一下,发现这显然是不可能的。因此我们构造出的解合法,且总点数最小。

最大独立集

最大独立集:选最多的点,满足两两之间没有边相连。

二分图的最大独立集 = 总点数 - 最小点覆盖。

解的构造

二分图的最大独立集是最小点覆盖的补集。

可以根据定义证明:最小点覆盖是每条边只要一个端点被选,那么它的补集就是每条边至多有一个端点被选,即最大独立集。

最大团等于总点数减去补图的最大独立集。

[HAOI2017] 新型城市化

在补图上考虑问题。由于题目保证了原图可以划分为不超过两个团,这条性质等价于补图至少可以划分为两个独立集,进一步等价于补图是一个二分图。
我们的目标变成:在二分图上删一条边,判断最大独立集是否变大。
根据最大独立集的性质,我们判断的就是最大匹配是否减小,即判断哪些边是二分图最大匹配的必须边。可以利用上面的结论,先跑 dinic,再在残量网络上跑一遍 tarjan 求出答案。

偏序集

定义

偏序集:集合中部分元素可以比较大小。
全序集:集合中所有元素都可以比较大小。
链:全集的一个子集满足其是全序集。
反链:全集的一个子集满足所有元素都不可以比较大小。
链覆盖:若干的链的并集满足是全集,且两两之间没有交集。反链覆盖同理。
最长链:所有链中元素个数最多的集合,最长反链同理。

最小不可重链覆盖

因为不可重覆盖,可以将每个点拆为一个入点和一个出点。在两类点之间按照原图连边。
跑二分图最大匹配即可,答案为总点数减去最大匹配。

最小可重链覆盖

通常有三种办法(摘自 louis 的 PPT):

  • 跑传递闭包后转为不可重覆盖,可重路径一定能在新图上对应一组不重路径。
  • 同样是拆点,设分别为 \(a_i,b_i\),先连源汇点,然后 \(a_i\to b_i\) 下界为 \(1\),原图的边连上 \(b_j\to a_i\),所有边上界均
    为 \(\inf\),跑上下界最小流即可。
  • 还是拆点,考虑改造一下不可重复覆盖的二分图,先连源汇点,上界均为 \(1\),\(b_i\to a_i\) 上界为 \(\inf\),原图的边
    \(a_i\to b_j\) 上界为 \(\inf\),这样就相当于在二分图上跑传递闭包了。

Dilworth 定理

一个偏序集中的最长反链大小,等于其中最小不可重链覆盖大小。

推论:一个 DAG 中最长反链的大小,等于其中最小可重链覆盖大小。

DAG 上最长反链的构造

模板:[CTSC2008] 祭祀

首先对 DAG 跑传递闭包,转为偏序集。拆点,转为二分图,并构造其最大独立集 \(I\)。
那么我们取出所有 \(x_{in}\in I\) 且 \(x_{out}\in I\) 的点 \(x\),它们构成原图的最长反链。
换句话讲:取出所有 \(x_{in}\) 被 dfs 到,且 \(x_{out}\) 未被 dfs 到的点,这些点组成了 DAG 的最长反链。

证明略。

上下界网络流

写不动了,这部分先咕着。考完 noip 再说。

标签:二分,连边,匹配,技巧,覆盖,常见,最小,SCC
From: https://www.cnblogs.com/ying-xue/p/17825885.html

相关文章

  • 蓝桥杯管道 -- 二分, 区间覆盖
    蓝桥杯管道--二分,区间覆盖原题链接参照执梗大佬的代码,我太菜了wuwuwu......importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;importjava.util.Scanner;/***ClassName:Main12*Package:*Description:**@author:LH寒酥......
  • MIME类型介绍及常见文件对应关系
    MIME(MultipurposeInternetMailExtensions)类型是一种用于描述消息内容的格式。它的目的是为了让不同类型的应用程序之间能够互相传输和处理消息。MIME类型通常由两部分组成:一部分是主类型(如文本、图像、音频、视频等),另一部分是子类型(如纯文本、JPEG图像、MP3音频等),两者之间用斜杠......
  • 一个Git clone仓库的指定目录命令对比国内外常见AI(一)使用ChatGPT3.5
    通常情况下,我们会克隆整个Git仓库,但有时候我们只需要其中某一个目录或文件,这时候只克隆子目录会更加方便。这个需求好像不是经常用到,搜索结果也是五花八门,有些完全达不到要求,正好用这个机会测试一下最近大火的AI看看是否足够智能。国外ChatGPT3.5(找一个可以访问的就好,ChatGPT4没找......
  • 在python开发过程中常见的异常错误
    下面这些也是常见的异常错误,在报错的时候不要害怕,记住这些常见的单词。AttributeError尝试访问未知的对象属性EOFError用户输入文件末尾标志EOF(Ctrl+d)FloatingPointError浮点计算错误GeneratorExitgenerator.close()方法被调用的时候ImportError导入模块失败的时候KeyboardInte......
  • Lumerical Script 实用编程技巧
    1如何实现程序的中断,执行另一段程序?方法1 但是这个方案涉及到另一个问题?2如何实现分析组内部变量的输出?可以通过addanalysisresult("变量名");将内部变量作为结果输出,为外部调用。......
  • 【小技巧】 如何利用 wget 命令在 Linux 系统上下载自己的 OneDrive 上的大文件
    最近有一个在Linux系统上利用wget命令下载自己账号的OneDrive上的大文件的需求。在网上找了许多方法(利用F12之类的)都不是很灵,最后终于探索出了一个非常简单的方法。方法通过360浏览器X登录OneDrive,进入需要分享的文件界面。(这里吐槽一下Chrome的下载器,做得实在不怎......
  • TypeScript的5个常见用法
    TypeScript是一种静态类型的JavaScript超集,它提供了额外的类型系统和一些ECMAScript新特性的支持。以下是TypeScript的一些常见用法:1:类型注解:TypeScript允许在变量、函数、参数、返回值等地方添加类型注解,明确指定变量的类型。例如:letname:string='John';functiongr......
  • 一个常见的 JavaScript 解构陷阱
    在日常的JavaScript编码中,我们经常使用解构语法来提取对象中的属性。假设我们有一个名为fetchResult的对象,代表从接口返回的数据,其中包含一个字段名为data。constfetchResult={data:null};在提取data字段时,为了避免接口未返回该字段而导致的问题,我们常常会使用......
  • 常见面试题-Spring的aop和ioc如何实现?
    Spring的aop和ioc怎么实现?Spring的IOC是如何实现的呢?Spring的IOC是通过工厂+反射去实现的,在IOC中,Spring会将创建的Bean都放在工厂中,我们可以通过@Configuration来定义配置类,在配置类中通过@Bean来将Bean创建在Bean工厂中,在对Bean进行实例化时,使用的......
  • 抖音自动功能的常见功能及相关代码!
    随着抖音的普及,越来越多的用户想要通过抖音自动功能来实现一些自动化操作,以提高自己的抖音账号运营效率,但是,对于很多新手来说,开发一款抖音自动功能需要了解哪些常见功能和相关代码是一个比较困惑的问题。本文将介绍一些常见的抖音自动功能及相关代码,帮助大家更好地了解和开发自己的......