[专题总结]二分图和网络流(理论篇)
二分图
二分图最大匹配
二分图的一组匹配就是一个边集,其中任意两条边没有公共顶点。
求最大匹配的过程:建一个图, \(S\) 向左部连 \(1\),右部向 \(T\) 连 \(1\) ,跑最大流,中间的边被流了就是匹配边。
点覆盖
是一个点的集合,使得所有的边至少有一个顶点在该集合内
- 最小点覆盖=最大匹配
证明: 首先最小点覆盖的下界是最大匹配,因为所有匹配边两边至少有一个点需要选择。
构造一种选择恰好最大匹配个点的方案,给出构造方法。
先跑出最大流,然后从右侧所有非匹配点开始 dfs, 从右侧向左侧走,只能走非匹配边,从左侧到右侧走,只能走匹配边,最后,取出所有左边的被 dfs 到的点和右边的未被 dfs 到的点,就是最小点覆盖。
证明:一条边不被覆盖当且仅当左边未被 dfs 到,右边被 dfs 到。
右边被 dfs 到了,他如果是非匹配点,他必将便利左侧所有相连点。
如果他是匹配点,那么他肯定是由左侧的匹配点过来的,过来的左侧点肯定被访问了,其他的左侧点会被他访问。
所以,一个与右侧被 dfs 到的点相连的所有左侧点都会被 dfs 到,不存在上述情况。
似乎还叫什么定理,例题:https://www.luogu.com.cn/problem/P6220
Tip: 最小割中的割边:并不是剩余容量为 \(0\) 就是割边,找割边需要先跑最大流,再从 \(S\) 开始 \(dfs\) 找到属于 \(S\) 集合的点,剩下的点属于 \(T\) 集合,两个集合之间的连边容量必定为 \(0\) ,是割边。
独立集
是一个点的集合,使得这个集合内任意两个点没有边相连
- 最大独立集=\(|V|-\)最小点覆盖
证明:首先独立集上界是 \(|V|-\) 最大匹配,因为如果选择更多,根据鸽巢原理,至少会有两个点同时在最大匹配中,必定不独立。
构造一种 \(|V|-\)最小点覆盖的方案,就是选择最小点覆盖的补集。
因为最小点覆盖把每条边的至少一个顶点覆盖了,所以剩下的点连的边已经没有完整的边了,所以肯定是独立集。
边覆盖
是一个边的集合,是的所有的点都是这个集合中的某条边的顶点
- 最小边覆盖=最大独立集
证明:首先最小边覆盖的下界是最大独立集,因为最大独立集内每个点都需要单独的一条边去覆盖。
构造一种最大独立集条边的方案,先选择所有匹配边,假设有 \(m\) 条。
这时候,还剩下 \(n-2m\) 个点没有覆盖,因为最小点覆盖的集合肯定是匹配点的集合,所以所有未匹配点都属于最大独立集,给这 \(n-2m\) 个每个点点任意选一条边即可。
最后选了 \(m+n-2m=n-m\) 条边,等于最大独立集。
路径覆盖
对于一个 DAG,是一个路径的集合,使得每个点都被至少一条路径覆盖
先把每个点 \(x\) 拆成入点 \(x_1\) 和出点 \(x_2\) ,若 \((u,v)\),则在 \(u_1,v_2\) 之间连一条边,不难发现新图是一个二分图。
最小不相交路径覆盖= \(|V|-\) 最大匹配。
证明:考虑一开始,匹配 \(0\) 条边,需要 \(|V|\) 个路径才能覆盖,每次匹配相当于把每个两个点放到一个集合,也就相当于少一条路径就能覆盖,最大匹配就是最小的路径覆盖。
最小可相交路径覆盖:先传递闭包,再最小不相交即可。
证明:原图传递闭包后,一条新图中的路径可以表示原图中一条断断续续的路径,把原图中相交的部分在新图中改成断断续续,就不相交了。
Dilworth 定理 与 集合论相关
传递闭包
跟2017年的论文里面学习,只学习了一部分。
若 \((i,j)\) 有边, \((j,k)\) 有边,则让 \((i,k)\) 有边。
实现采用和 Floyd 算法类似的方式,枚举中间点。
设 \(f_{i,j,k}\) 为只考虑前 \(i\) 个点, \(j,k\) 是否有关系。
转移考虑是否经过通过第 \(i\) 个点, \(m_{i,j,k}=m_{i-1,j,k}|(lk_{j,i}\&lk_{i,k})\)
可以滚动数组,所以有代码
for(R k = 1; k <= n; k++) for(R i = 1; i <= n; i++) for(R j = 1; j <= n; j++)
f[i][j] |= f[i][k] & f[k][j]
由于是 bool 值,可以 bitset 优化一下。
bitset<N>f[N];
for(R k = 1; k <= n; k++) for(R i = 1; i <= n; i++) if(k != i && f[i][k]) f[i] |= f[k];
还可以先缩点再 bitset 优化拓扑排序,复杂度 \(\frac {nm} {w}\)
当然和可以使用经典的 bitset 分块,也就是分成几块分别做。
Dilworth定理:最大反链等于最小链覆盖
证明方法一:归纳
link 挺厉害的证明,取出所有交点的最大值构成一个反链这个操作根本学不来。
证明方法二:构造性证明:
设最小链覆盖需要 \(n\) 个链,那么最大反链的大小不会超过 \(n\) , 因为每条链最多选择一个元素。
构造一个大小为 \(n\) 的反链,一开始我想直接构造,尝试了半天都不对,后来向大佬学习了结合网络流的构造方法。
二分图知识可以知道 DAG 的可相交最小路径覆盖是先传递闭包,再转化成二分图,之后 DAG 的最小链覆盖= \(|V|-\) 转化后二分图的最大匹配。
又因为转化后二分图的独立集肯定是原二分图的反链(因为已经传递闭包过了,二分图中独立集互相不可到达,故在 DAG 中必定也互相不可到达),又因为证明了最大独立集=\(|V|-\) 最大匹配。
所以 偏序集的最小链覆盖=最大反链。
链接内的证明全都是构造性证明(有构造方法),故此证明也是。
Dilworth对偶定理:最大链等于最小反链覆盖
证明: 和原定理证明一样,取原图关于完全二分图的补集即可。
Dilworth定理配合鸽巢定理的推论
集合大小是 \(mn+1\), 则要不有 \(m+1\) 的链,要不有 \(n+1\) 的反链。
若都没有,则最多有 \(m\) 个链,每个链最多 \(n\) 个元素,集合大小最大 \(nm\) .
Dilworth定理在多维偏序中应用
导弹拦截:最小上升子序列覆盖等于最长不升子序列长度。
这是二维的偏序,也就是序列下标和值的笛卡尔积,可比定义为 \(i<j, val_i<val_j\)。
那么你要反链,任意一对 \(i,j\) 都需要满足 \(i<j \&val_i\geq val_j\) 或者 \(i>j \& val_i \leq val_j\)
这恰好就是最长不升子序列,举个扩展到三维的例子,定义可比为 \(a_i<a_j \& b_i < b_j \& c_i < c_j\)。
那么,反链内的任意两个元素 \((i,j)\) 不能有 \(a_i<a_j \& b_i < b_j \& c_i < c_j\) 或者 \(a_i>a_j \& b_i > b_j \& c_i > c_j\) 。
本质是对笛卡尔积的理解了。
总结,一种证明至多至少的方式:先证明一个界是 \(x\),在构造另一各界是 \(x\) 的一种方案。
Vizing 定理,图着色相关
点着色
给每个点染色使得没有一条边两边的颜色相同,也就是独立集划分。
这部分并没有什么优秀的算法,只有近似算法,可以证明上界是 \(max(deg)+1\)
给出一个把点按度数从大到小排序之后颜色数最多是 \(\displaystyle max_{i=1}^n min\{deg(v_i)+1, i\}\)
就是把剩下的点按度数从大到小排序,然后把第一个点染成当前染色次数的染色 \(i\)。
然后从前往后贪心,如果当前点染成 \(i\) 不冲突,那么就把他染成这个颜色,然后删掉。
最后就得到了一组染色,就是这个算法得到的结果,上界是\(\displaystyle max_{i=1}^n min\{deg(v_i)+1, i\}\)
边着色
给每条边染上色使得没有两条共端点的边颜色相同。
Vizing 定理:
- 对于任意一张简单图最大度数是 \(mx_{deg}\) , 最少需要 \(mx_{deg}/mx_{deg+1}\) 个颜色把整张图边染色。
其中第一类称为 一类图,第二类称为二类图,没有什么好的办法判断一张图是第一类还是第二类,但绝大多数图都是第一类。
最大度数 \(\geq\) 7, 肯定是第一类图,二分图是第一类图,至于证明,一般图不会证。
二分图的 Vizing 定理构造性证明
枚举每一条边,找到 \(f,t\) 最小的没使用过的颜色 \(mn_f, mn_t\), 如果 \(mn_f==mn_t\) 直接染上这种颜色。
否则假设 \(mn_f<mn_t\), 那么考虑把 \(t\) 的 \(mn_f\) 的边改成 \(mn_t\)。
如果对 \(t\) 的连边有影响,就不断递归找下去,找出一条增广路,由于找的是最小的没使用过的颜色,一定不会出环。
着色计数
一张无向图 \(G(V,E)\) 用小于等于 \(k\) 个颜色点着色的方案数是 \(\displaystyle \sum_{S \subseteq E} (-1)^{|S|} k^{c(G(S))}\)
\(G(S)\) 代表只保留 \(S\) 集合的边的图, \(c(G)\) 代表 \(G\) 的联通分量个数,证明考虑容斥枚举不合法的边。
当然还可以使用枚举联通块划分进而枚举子集的经典优化, ABC236 Ex 和下面3个题都是这个套路,同时这个是求 “满足某种限制下 ... 互不相同的方案数”的一大法宝。
着色计数-小练习!
1.计算一个 \(n\) 个点的环用至多 \(k\) 色染色的方案数
当然可以去 Dp, 这里利用上述的公式进行推导, 因为 \(<n\) 条边的时候图一定不连通,所以联通块=点数-边数
2.计算一个 \(n\) 个点的,包含一个长为 \(a\) 的环的基环树用至多 \(k\) 色染色的方案数
第一部分必定包含环,第二部分必定不包含环。
虽然这是最基本的图染色计算公式,但是还是可以考虑用它去扩展到特殊情况
无环定向数
令 \(X(G,k)\) 为图 \(G\) 的色多项式,那么把 \(t\) 带入 \(X(G,k)\) 得到的就是用 \(\leq t\) 种颜色给 \(G\) 点染色的方案数。
色多项式是一个 \(n\) 次的多项式, 因为 \(X(G,k)=\sum_{k=0}^n \binom x k g(k)\) \(g(k)\) 是划分成 \(k\) 个独立集的方案数。
- 定理:无向图 \(G\) 的无环定向数 (给每一条边定向,使得有向图是一个 DAG) 为 \(X(G,-1)\) 。
一般图来说,我们可以求出色多项式的 \(n\) 个点值,然后带入 \(-1\) 即可,特殊图我们有表达式之后不用顾虑组合意义直接带入 -1 即可。
定理证明,首先第二维是 \(-1\) 的原因是我们先考虑 \(E(G)=0\) ,那么 \(X(G,k)=k^n\)
\(X(G,-1)=(-1)^n, X(G,-1)*(-1)^n=1\) 符合没有边的图的无环定向方案数 \(=1\)。
然后考虑归纳,色多项式有一个递推式 \(X(G,k)=X(G-e,k)-X(G\cdot e,k)\) \(G\cdot e\) 代表的是把 \(e\) 这条边缩成一个点, \(e\) 两边的点删除,缩掉的点向 \(e\) 两边的点的并集连边的图。
这个递推式显然是正确的, 去掉 \(e\) 之后的染色方案可能在有 \(e\) 的时候不合法,原因是 \(e_f\) 和 \(e_t\) 颜色相同,每一种这样的情况,我们把 \(e_f,e_t\) 缩起来之后都是一个合法的染色方案 (钦定颜色相同,缩成一个点)。
然后考虑在边集上面归纳, \(X(G,-1)*(-1)^n=(X(G-e,-1)-X(G\cdot e, -1))*(-1)^n=X(G-e,-1)*(-1)^n+X(G\cdot e, -1)*(-1)^{n-1}\) 我们只需要证明 \(G\) 的无环定向方案数是 \(G-e\) 的方案数和 \(G\cdot e\) 的方案数之和即可。
考虑 \(G-e\) 的每一种拓扑序,我们把 \(e\) 两端 \(u,v\) 中拓扑序小的连向拓扑序大的,肯定对 \(G\) 是一种合法方案。
还有一种可能性就是 \(G-e\) 中 \(u,v\) 没有路径,意味着这条边可以随便连, \(u,v\) 没有路径,我们把 \(u,v\) 缩起来,肯定无环,所以,每一种 \(u,v\) 之间缩起来且无环的图对应一个 \(G-e\) 中 \(u,v\) 没有路径的图,这种路径在 \(G-e, G\cdot e\) 中被我们个计算一遍,所以是正确的。
Hall定理
设二分图中集合 \(S\) 的邻域 \(N(S)\) 为他连向的边在另一个集合内有多少点。
Hall定理 :一个二分图,两部为 \(X,Y, |X| \leq |Y|\),存在一个大小为 \(|X|\) 的匹配,当且仅当 \(\forall S \subseteq X\), 有 \(|N(S)| \geq |S|\)
证明:
必要性: 如果存在一个 \(S\) 使其不成立,那么 \(S\) 集合内的所有点都无法全部匹配,原图自然无法全部匹配。
充分性:考虑直接构造出来最大匹配,使用数学归纳法,现在假设所有 \(< n\) 的都已经成立。
找到最小的 \(S\), 其 \(N(S)=S\), 然后把他全部连上(由归纳知他们有完美匹配),然后规约到更小规模的问题。
假设此时不存在 \(N(S)=S\), 那么直接找到任意一个点,随意连一条边然后把它删掉,肯定不会因为他删掉出现不符合 hall 定理的情况,因为所有人都大于,规约到 \(n-1\) 的问题。
推论1:一个二分图,两部为 \(X,Y, |X| \leq |Y|\),存在一个大小为 \(|X|-t\) 的匹配,当且仅当 \(\forall S \subseteq X\), 有 \(|N(S)| \geq |S| - t\) 证明和 hall 定理基本一样
推论2:对于多重匹配, \(u\) 可以匹配 \(W_u\) 次, 那直接把 \(u\) 拆成 \(W_u\) 个点, 转成二分图,即可使用 Hall定理
推论的过程中,我们把 \(u\) 拆成的点连出的边是相同的,所以实际上我们只需要关注每个点选择他所有点时候符不符合即可(因为不选他所有点不会让 \(|N(S)|\) 变小,只会让 \(|S|\) 变小。
所以,可以得到二分图存在带权完美匹配 (\(\sum W\) 小的一侧全部匹配) 的条件是 \(\forall S \subseteq X\), 有 \(W_{N(S)} \geq W_{S}\)
推论3:一个 k 正则二分图,左右点数相等,必存在完美匹配
一个无向图,每个点度数都是 \(k\) ,则称这个图为 k-正则图。
假设存在一个集合 \(S\), \(|N(S)|<|S|\), 由于 \(|S|\) 向 \(|N(S)|\) 连了 \(|S|*k\) 条边,所以 \(N(S)\) 至少有 \(|S|*k\) 条边,但是 \(N(S)\) 只有 \(N(S)*k\) 条边,与假设矛盾,故推论成立。
推论4:一个二分图,左侧的点至少和 \(k\) 个点连边,右侧的点至多和 \(k\) 个点连边,则存在完美匹配
左侧一个大小为 \(|S|\) 的子集,右侧有 \(|T|<|S|\), 左侧连了 \(\geq |S|*k\), 然后右侧有 $ \leq |T|*k$ 条边,然后和 3 一样。
关键 推论5:二分图的最大匹配为 \(|X|-max(|S|-|N(S)|)\), 其中 \(S\subseteq X\) (X 是较小的一部)
其实说是关键也没什么,可以直接根据推论1证明,既然有 \(|X|-t\) 的要求是那个,我就找到最大的破坏要求的数,然后把要求调整,这样就肯定附和条件了。
还有一个比较启发的证明,同样可以用来证明 hall 定理。
枚举一个点集 \(S\), 然后割掉 \(S\) 的补集 \(X-S\), 此时要想成为原图的一组割,还要割掉 \(N(S)\), 把柿子转化发现时 \(\min(X-|S|+|N(S)|)\), 就是割取最小值,即最小割,也就是最大匹配。
证明 hall 定理那个东西和 \(n\) 取 min 即可。
网络流-最大流/最小割
正确性
最大流的算法基于不断寻找增广路然后增广,其中关键的一点就是不存在增广路的时候一定是最大流
为证明这个,我们先给出一个关键的定理
最大流最小割定理
一个网络的最大流=最小割,割的定义是一组边集,断掉他们之后 \(S\), \(T\) 不连通,一般割也可以代指这个边集的容量之和。
我们定义一个流 \(f\) 关于一个割集 \(g\) 的流量 \(G_f(g)\) 代表这个流流过这组割集的流量。
可以证明,对于一个固定的流,任意一个割集 \(g'\) 的 \(G_f(g')=G_f(g)=|f|, |f|\) 代表这个流的流量。
因为流量守恒,初始假设 \(S\) 和剩下的所有点形成两个集合,他们之间割集的流量肯定是 \(|f|\), 你接着往 \(S\) 所在的集合加入任意一个不是 \(T\) 的点,不会改变 \(S\) 所在集合流出去了多少流量,因为每个不是 \(S\) 的点都只流出去 \(0\) 的流量。
所以,我们可以得到,对于任意一个流,都有任意一组割的容量 \(\geq\) 这个流的流量,也就是任意一个流 \(\leq\) 最小割。
至此,我们引出最大流最小割定理
- \(f\) 是 \(G\) 的一个最大流。
- \(f\) 在 \(G\) 中不存在增广路。
- \(|f| = G_f(g)\), \(g\) 是该网络任意一个切割。
这三个条件是等价的。
\(1 \Rightarrow 2\), 若存在增广路,则一定不是最大流
\(2 \Rightarrow 3\), 由于不存在增广路,所以 \(G\) 中没有 \(S\) 到 \(T\) 的路径,所以一个切割的流量=容量,否则若有一条在割集中的边流量不等于容量,则存在一条 \(S\) 到 \(T\) 的路径,与不存在增广路矛盾。
\(3 \Rightarrow 1\), 由于任意一个流的流量 \(\leq\) 最小割,存在一个割等于流量,隐含着他是最大流。
复杂度
/
EK 复杂度证明
EK 采用从短到长依次确定增广路的方法,可以证明增广路不会变短,一次寻找增广路并增广的时间显然是 \(O(m)\) , 我们只需要证明最多 \(nm\) 次增广。
先证明增广路不会变短,我们只需要证明 \(f \rightarrow f'\) 任意一个点的 \(dis \leq dis'\)。
假设从 \(f \rightarrow f'\) 的过程中增广路变短了,那么假设 \(u\) 是 \(dis'\) 最小的 \(dis'\) 变小的点。
首先,假设 \(v\) 是 \(dis'_u\) 最短路上的前驱,那么 \((u,v)\) 这条边如果不是 \(f \rightarrow f'\) 这次增广出现的,那么一定不合法,因为 \(u\) 是最小的 \(dis'\) 变小的点,如果合法那么 \(dis'_v\) 肯定也会变小。
其次,如果 \((u,v)\) 是新出现的,那么 \(v\) 本来是 \(u\) 的一个后继,现在变成了 \(u\) 的前驱,由于我们找的是最短路,所以 \(dis'_u\) 至少要增大 \(2\)。
接着证明最多 \(nm\) 次增广。
我们每进行一次增广,肯定会导致一条边 \((u,v)\) 消失,如果这条边再次出现,那么肯定是从 \(v\) 到 \(u\) 的一条增广路。
由于我们找的是最短路, 那么,消失的时候 \(dis_u=dis_v-1\), 出现的时候 \(dis_u=dis_v+1\), 这么一折腾, \(dis_u\) 至少加 \(2\) , 由于 \(dis\) 不减,所以每个点的 \(dis\) 最多增加 \(n/2\) 次,一共 \(m\) 条边,每条边最多消失 \(n/2\) 次,故总增广次数是 \(nm\) 的。
Dinic 复杂度证明
在证明 EK 的过程中我们可以发现,增广长都为 \(dis\) 的路,可能带来长度为 \(dis+2\) 的路,但不能带来 \(dis\) 的路。
也就是,如果我们能一次增广所有长度为 \(k\) 的路,那么我们只会增广 \(n/2\) 次。
Dinic 一次增广复杂度是 \(O(nm)\) 的,因为一共 \(m\) 条边,每条边最多在一条 \(O(n)\) 便利路径时消失一次。
一些特殊的复杂度
- 若是二分图,复杂度 \(\sqrt n m\)。
- 若容量全是 \(1\), 复杂度 $ \min(\sqrt m m, n^{2/3}m)$ 。
- 单位图(unit graph) 是指,所有的边的容量都是整数,且每一个不是 \(s\) 或 \(t\) 的点,要么出度为 1,连出去的边容量为 1,要么入度为 1,连进来的边容量为 1, 单位图上复杂度和二分图相同。
DAG最小路径覆盖
最大权闭合子图
给定一个 DAG, 每个点有一个点权,选出一个子图,使得这个子图内任意一个点连出的边都在这个子图内。
观察性质,如果所有点点权都是正数,那么肯定选择所有点。
问题就在于一些点权为负数的点,这启发我们对点权正负分类讨论。
我们选取一个点权是正数的点,就要被迫选取所有他连向的点权为负数的点。
我们用 \(S\) 向所有点权为正数的点连 点权的边,把所有点权为负数的点向 \(T\) 连点权的绝对值。
原图的边设置成正无穷,那么所有点权为正数的边-最小割就是答案。
考虑不选择了一个正数边,就相当于直接把他割掉。
选择,就相当于必须割掉他连向的负点的边,以及负点连向的负点的边。
上下界网络流
无源汇上下界可行流
无源汇流 : 满足流量平衡即可,大概是几个“涡流”。
上下界 :每条边需要满足其流量在 \([L,R]\) 内。
先让每条边流其下界,那么现在的网络就只有下界了,但是他现在可能是不平衡的。
我们的目的就是添加一个附加的流,并且不超过 \(R\),使得网络平衡。
我们统计每个点流入-流出= \(M_i\)
若 \(M_i=0\) ,则说明他已经平衡。
若 \(M_i>0\) ,则说明流进来多了,我们想让他流走,那么就用超级原点 \(S'\) 想他连 \(M_i\) 的边,实际意义是原点把他多余的流量推走。
若 \(M_i<0\) ,同理用它向 \(T'\) 连 \(-M_i\) 的边,代表需要有 \(M_i\) 的流量流进来。
所以我们如上建图之后,在 \(S',T'\) 之间跑一个最大流,如果每条边都满流就说明存在一个调整方案,即存在一个可行流。
有源汇上下界可行流
从 \(T\) 到 \(S\) 建一条 \([0,\infty]\) 的边,然后他就变成了无源汇。
如果有解,那么流量就恰好是这条边的流量(电池内部负极流向正极, 注意我们要求的源汇之间的流量并不是增广的流量,而是电池边的流量!
有源汇上下界最大流
先得到可行流,然后去掉超级源汇,直接在 \(S,T\) 跑一次最大流即可得到,答案是可行流流量+最大流流量。
因为可行流已经让流量守恒,跑最大流不会改变流量守恒的性质,所以可以直接跑一下去调整。
有源汇上下界最小流
先可行流,去掉电池边,然后从 \(T\) 向 \(S\) 跑,答案是可行流流量-最大流流量。
最小割性质,最小割树
最小割必须边和可行边:建出残量网络后缩点成 DAG 去判断,具体参考 ix35。
最大匹配必须边和可行边:建出残量网络后缩点成 DAG 去判断,可行就是在当前匹配里或这条边两端在一个 SCC 里,必须就是在当前匹配里且这条边两端不在一个 SCC 里,具体参考 ix35。
最大匹配必须点和可行点:可行点仿照上栗,如果是非匹配点且度数不为0,一定可以找到一条半增广路。
必须点:是匹配点并且匹配边另一侧的点连向的点都是匹配点,对应到图中,即和S不在同一个SCC里面。
- 网络流中可以存在若干可以增广的环,增广他们并不会改变流量但会改变流结构。
- 残量网络上的 SCC 在网络流分析方面是一个利器。
网络流-费用流
特殊的费用流模型
最大费用任意流 & 正费用最大流
性质:每次寻找的增广路长度(费用)是单调不降的,EK复杂度已经证明过了。
也就是,我们得到的总费用具有凸性,具体来说,这个右下凸包。
利用这个,我们来可以解决一些特殊的需求
比如这两类,我们都是要找最长路去增广,第一个费用负了就不增广。
第二个只要费用 > 0 就一直增广,注意最后一个增广可能不增广一条满流。
带有负环的费用流问题
强制所有负权边满流,然后流量不守恒,但已经没了负环。
强制满流的代码实现
inline void link(int f, int t, int w, int c){
if(c >= 0) add(f, t, w, c), add(t, f, 0, -c);
else{
tot[t] += w, tot[f] -= w, ansc += w * c;
add(f, t, 0, c), add(t, f, w, -c);
}
} // 注意不要忘记把费用加到 ans 里面。
和上下界一样的手法,建超级源汇去处理,跑最小费用最大流, 然后为了最大流,还需要去掉电池边,再跑一遍真正源汇的最小费用最大流即可。
注意我们要求的源汇之间的流量并不是增广的流量,而是电池边的流量!
有源汇上下界最小费用可行流
最大流变成最小费用最大流即可,一开始我有一个疑问,存不存在费用的增广路,现在看来他不是问题,因为肯定不存在。
如果存在费用的增广路并且不会改变流量,那么最小费用最大流肯定回去跑它,而不会留下来, code。
有源汇上下界最大费用可行流
找最长路即可,但是可能出现负环,需要配合负环费用流。