OI+ACM 笔记:F - 图论

 


F - 图论 杂项

图论基础

参考:

图的储存

邻接表的封装

邻接表的储存成对变换:在具有双向边的图中,把正反方向的边分别储存在邻接表的位置 n,n+1n 为偶数),就可以通过 xor 1 的操作获得当前边的反向边的储存位置。具体实现时,初始化要令 tot = 1

图的遍历

BFS

  • Breadth First Search。

DFS

  • Depth First Search。

拓扑排序

拓扑序:一张有向无环图中的一个节点序列 A,满足对于图中的每条边 (x,y)xA 中都出现在 y 之前。

  • 维护一个入度为 0 的点集 S。每次扩展时,从 S 中取出任意一点 u 加入拓扑序,然后枚举 u 的所有出边,若某个出点 v 在删除了 (u,v) 这条边之后入度变为 0,则将 v 加入点集 S
  • 由拓扑排序的算法得到的拓扑序按照层次分层,但同一层次的节点未必需要在拓扑序中相邻。
  • 若要求字典序最小的拓扑序,将队列换成优先队列即可。

欧拉路、欧拉回路

欧拉路:恰好不重不漏的经过每条边一次(可以重复经过图中的节点)的通路。

欧拉回路:恰好不重不漏的经过每条边一次(可以重复经过图中的节点)的回路。

欧拉图:存在欧拉回路的无向图。

欧拉图的判定

  • 一张无向图为欧拉图,当且仅当无向图连通,并且每个点的度数都是偶数。
  • 一张有向图为欧拉图,当且仅当非零度点强联通,每个点的入度与出度相等。

欧拉路的存在性判定:一张图中存在欧拉路,当且仅当无向图连通,并且途中恰好有两个节点的度数为奇数,其他节点的度数都是偶数。这两个度数为奇数的节点就是欧拉路的起点 S 和终点 T

三元环计数、四元环计数

无向图三元环计数

  • 将所有点以度数为第一关键字(小到大)编号为第二关键字(小到大)排序,将所有边按排名从小到大定向,形成一张 DAG。
  • 此时所有三元环的边向情况,只有 xyyzxz 这一种情况。
  • 枚举点 x,第一轮枚举 x 在新图中的出边,将所到达的点 z 打上标记;第二轮枚举 x 在新图中的出边,对于所到达的点 y,再枚举 y 在新图中的出边到达的点 z,如果 z 上有标记,则 x,y,z 构成三元环。

无向图三元环计数,时间复杂度O(mm)

无向图三元环计数,时间复杂度分析

  • degu 为原图中点 u 的度,outu 为新图中点 u 的出度。可证 outuO(m) 级别。
    • degum,则 outum
    • degu>m,则 u 在新图中指向的点的度数大于 m,故 outum
  • 上述流程的复杂度,相当于对定向后每条边 (u,v)voutv 求和。每条边的贡献为 O(m) 级别,故上述流程的复杂度为 O(mm)

无向图三元环计数的推论:无向图的三元环个数为 O(mm) 级别。

有向图三元环计数:转化为无向图三元环计数,找到三元环时判断方向即可。

竞赛图三元环计数:记点 i 的出度为 outi,则三元环个数为

(n3)i=1n(outi2)

无向图四元环计数

  • 将所有点以度数为第一关键字(小到大)编号为第二关键字(小到大)排序,将所有边按排名从小到大定向,形成一张 DAG。
  • 此时所有四元环的边向情况,只有两条形如 (x,y)yz 的路径拼起来的情况:
    • xy1y1zxy2y2z
    • xy1y1zxy2y2z
    • xy1y1zxy2y2z
  • 枚举点 x,再枚举 x 在原图中的出边,对于所到达的点 y,再枚举 y 在新图中的出边到达的点 z(为避免第三种边向情况重复计数,此处枚举到的 z 应满足 rkx<rkz),则先前枚举的所有形如 (x,y)yz 的路径都与当前枚举的路径构成四元环。

无向图四元环计数,时间复杂度O(mm)

无向图四元环计数,时间复杂度分析:同无向图三元环计数。

Prufer 序列

Prufer 序列:一个包含 n2 个取值范围在 [1,n] 中的正整数的序列。可以理解为带标号的完全图生成树数列的双射。

Prufer 序列构造:每次选择一个编号最小的叶结点并删掉它,并且在序列中记录下它连接到的那个结点。重复 n2 次后,只剩下两个节点后停止。

Prufer 序列性质

  • 在构造完 Prufer 序列后原树中会剩下两个结点,其中一个一定是编号最大的点 n
  • 每个节点在 Prufer 序列中的出现次数是其度数减 1,叶节点不出现。

树转 Prufer 序列

  • O(nlogn) 构造:堆优化。
  • O(n) 构造:注意到叶节点个数是单点不增的。考虑维护一个指针 p,初始时 p 指向编号最小的叶节点。同时维护每个节点的度数,考虑重复如下过程:
    1. 删除节点 p,并检查是否产生新的叶节点。
    2. 如果产生新的叶节点 x,比较 x,p 的大小关系,若 x>p,则不做其他操作;若 x<p,则立刻删除 x,然后检查是否产生新的叶节点 ...(重复步骤 2),直到未产生新节点或新节点的编号 >p
    3. p 自增,直到遇到一个未被删除的叶节点为止。

Prufer 序列转树:通过 Prufer 序列反推每个节点的度数。依次枚举 Prufer 序列的每一个点,每次选择一个度数为 1 且编号最小的节点,与当前枚举到的 Prufer 序列的点连边,并且令这两个点的度数减 1。重复 n2 次后,只剩下两个度数为 1 的节点,将这两个点连边。

  • O(nlogn) 构造:堆优化。
  • O(n) 构造:同 "树转 Prufer 序列"。

Cayley 公式(有标号完全图生成树计数):有标号完全图有 nn2 棵生成树。

F - 图论 最小生成树

Kruskal

  • O(n+mlogm)

Kruskal 重构树

Kruskal 重构树:按 Kruskal 的流程,每加入一条边 (u,v,w),就新建一个点 x,同时将 x 的点权设为 w,将 u,v 所在的树的根节点分别设为点 x 的左儿子与右儿子。在进行 n1 轮合并后,得到了一棵恰有 n 个叶子的二叉树,同时每个非叶子节点恰好有两个儿子,这棵树即为 kruskal 重构树。

Kruskal 重构树的简单性质

  • kruskal 最小重构树是大根堆,kruskal 最大重构树是小根堆。
  • kruskal 最小重构树中,两叶子节点之间 LCA 的权值,对应原图中两点之间所有简单路径上最大边权的最小值。
  • kruskal 最小重构树中,对于叶子节点 x 到根的路径上权值 val 的最浅节点,其子树内的所有节点,即为从 x 开始只经过边权 val 的边所能到达的节点(满足两点之间所有简单路径上最大边权的最小值 val)。

Prim

  • O(n2)

Brouvka

  • 初始时,每一个点都是一个连通块。每一轮,遍历所有点和边,连接一个连通块中和其他连通块相连的最小边。
  • O((n+m)logn)

F - 图论 最短路径

Dijkstra

  • Dijkstra:O(n2)
  • Dijkstra + Heap:O((n+m)logm)

Bellman-ford & SPFA

  • SPFA:O(nm)

Bellman-Ford 判负环:若经过 n 轮迭代后,图中仍有能更新的边,则图中有负环。

SPFA 判负环:设 cntx 表示 1x 的最短路包含的边数。在迭代的过程中,若发现 cntyn,则图中有负环。

Floyd

  • Floyd:O(n3)
  • Floyd 本质上是 dp。定义 f(k,i,j) 表示允许经过 1k 号点作为中间点(除了 i,j 分别为起点终点,经过的其他点只能是 1k 的点)的情况下,点 i 到点 j 的最短路。通过滚动数组优化掉了阶段维,才得到最常见的 Floyd 写法。如果以任意的顺序枚举 k,得到的 f(i,j) 即为允许经过枚举过的点作为中间点的情况下,点 i 到点 j 的最短路。

差分约束

差分约束:一种特殊的 n 元一次不等式组,包含 n 个变量 x1,x2,,xn 以及 m 组限制关系 xixjck

  • xixjck 可以变形为 xixj+ck,形似三角形不等式,因此从点 j 向点 i 连一条长度为 ck 的有向边。
  • 若存在负环则无解,否则最短路即为一组合法解。

同余最短路

同余最短路,问题 1:给出 a1,a2,,an 和一个模数 K,对于每一个 p[0,K) 求使得 (aixi)modK=paixi 最小值。

  • K 个点,编号为 0K1
  • 对于每一个 p[0,K) 和每一个 ai,令 p(p+ai)modK 连一条长度为 ai 的边。转化为图论模型。

同余最短路,问题 2:给出 a1,a2,,an 和一个上界 H,求 aixi 的数值在 [0,H] 有多少个解。

F - 图论 连通性

无向图 tarjan

时间戳与追溯值

时间戳 dfnx:在深度优先遍历的过程中,节点 x 第一次被访问时的时间顺序。

追溯值 lowx:以下节点的时间戳的最小值

  • subtree(x) 中的节点。
  • 通过一条非搜索树边,能够到达 subtree(x) 中的节点的点。

时间戳 dfnx 与追溯值 lowx 的计算方式:对整张图进行深度优先遍历,一开始 lowx=dfnx,考虑从 x 出发的每条边 (x,y)

  • xy 的父亲,则

lowx=min(lowx,lowy)

  • (x,y) 为非搜索树边,则

lowx=min(lowx,dfny)

割点

割点:满足删去该点以及连接该点的边后,原图不连通的点。

割点判定法则:在搜索树上,若存在 x 的某个儿子 y 满足

dfnxlowy

x 为割点。特别地,若 x 为搜索树的根,则至少要找出两个满足条件的儿子。

割边

割边:满足删去该边后,原图不连通的边。

割边判定法则:在搜索树上,若 xy 的父亲,且满足

dfnx<lowy

(x,y) 为割边。

点双连通分量

点双连通:若删去任意一个点(除 u,v 以外),u,v 仍连通,则称 uv 是点双连通的。

点双连通图:不存在割点的无向连通图。

点双连通分量(v-DCC):无向图的极大点双连通子图。

v-DCC 的简单性质

  • 一张无向连通图是 v-DCC,当且仅当任意两个点都包含在至少一个简单环中。
  • 对于一个 v-DCC 的任意两个点,它们之间都有至少两个点不重复的路径。
  • 对于一个 v-DCC 中任意两个点,它们之间简单路径的并集,恰好完全等于这个 v-DCC。
  • 割点至少在两个 v-DCC 中,其他非割点属于且仅属于一个 v-DCC 中。

v-DCC 的缩点(圆方树)

  • 在圆方树中,原图中每个点对应一个圆点,每个 v-DCC 对应一个方点
  • 对于每个 v-DCC,令其对应的方点该 v-DCC 中的每一个圆点连边。每个 v-DCC 构成一个菊花图,多个菊花图通过原图中的割点连接。
  • 对原图做一遍无向图 tarjan。考虑一个 v-DCC 在 DFS 树中的最顶端节点 u,在点 u 处确定这个 v-DCC。对于一个树边 (u,v)u,v 在同一个 v-DCC 中且 u 是这个 v-DCC 中的最顶端节点,当且仅当 dfnu=lowv
  • 可以在 DFS 的过程中,维护一个栈,储存还未确定所属 v-DCC(可能有多个)的节点。找到 v-DCC 时,v-DCC 中除了 u 以外的其他点都集中在栈顶端,只需不断弹出栈顶直到弹出 v 为止。u 和被弹出的所有点,构成一个 v-DCC,都需要向新建的方点连边。

边双连通分量

边双连通:若删去任意一条边,u,v 仍连通,则称 uv 是边双连通的。

边双连通图:不存在割边的无向连通图。

边双连通分量(e-DCC):无向图的极大边双连通子图。

e-DCC 的简单性质

  • 一张无向连通图是 e-DCC,当且仅当任意一条边都包含在至少一个简单环中。
  • 对于一个 e-DCC 中的任意两个点,它们之间都有至少两个边不重复的路径。
  • 对于一个 e-DCC 中的任意两个点,它们之间简单路径的并集,恰好完全等于这个 e-DCC。
  • 割边不属于任意 e-DCC,其他非割边属于且仅属于一个 e-DCC。
  • 一张图经过 e-DCC 缩点后会得到树或森林。

e-DCC 的缩点

  • 对原图做一遍无向图 tarjan。考虑一个 e-DCC 在 DFS 树中的最顶端节点 u,在点 u 处确定这个 e-DCC。u 是这个 e-DCC 中的最顶端节点,当且仅当 dfnu=lowu
  • 可以在 DFS 的过程中,维护一个栈,储存还未确定所属 e-DCC(可能有多个)的节点。找到 e-DCC 时,e-DCC 中的所有点都集中在栈顶端,只需不断弹出栈顶直到弹出 u 为止。被弹出的所有点,构成一个 e-DCC。
  • 在找出了所有的 e-DCC 后,枚举原图中的所有边 (u,v),若 uv 不属于同一个 e-DCC,则在 u,v 所属的 e-DCC 之间连一条边。

有向图 tarjan

流图

时间戳 dfnx:在深度优先遍历的过程中,节点 x 第一次被访问时的时间顺序。

流图:给定有向图 G=(V,E),若存在 rV,满足从 r 出发能够到达 V 中的所有点,则称 G 是一个流图,其中 r 称为流图的源点。

流图中的有向边 (x,y) 分类:对于流图中的有向边 (x,y),必是以下四种之一

  • 树枝边。指搜索树中的边,即 xy 的父节点。
  • 前向边。指搜索树中 xy 的祖先节点。
  • 后向边。指搜索树中 yx 的祖先节点。
  • 横叉边。指除了以上三种情况之外的边,一定满足 dfnx>dfny

强连通分量

强连通:若既存在 xy 的路径,又存在 yx 的路径,则称 xy 是强连通的。

强连通图:任意两点都强连通的有向图。

强连通分量(SCC):有向图的极大强连通子图。

时间戳 dfnx:在深度优先遍历的过程中,节点 x 第一次被访问时的时间顺序。

追溯值 lowx:以下节点的时间戳的最小值

  • 栈中的节点。有向图 tarjan 在深度优先遍历的同时维护了一个栈,当访问到节点 x,保存从 x 出发的后向边横叉边形成环的节点:
    • 搜索树上 x 的祖先节点,记作 anc(x)
    • 已经访问过,并且存在一条路径到达 anc(x) 的节点。
  • 通过一条从 subtree(x) 中出发的有向边,以该点为终点。

时间戳 dfnx 与追溯值 lowx 的计算方式:对整张图进行深度优先遍历,一开始 lowx=dfnx,将 x 入栈,考虑从 x 出发的每条边 (x,y)

  • y 没有访问过,则说明 xy 的父亲,则

lowx=min(lowx,lowy)

  • y 被访问过,且 y 在栈中,则

lowx=min(lowx,dfny)

x 回溯之前,若 dfnx=lowx,则不断弹出栈顶直到弹出 x 为止。

SCC 判定法则:在 x 回溯之前,若 dfnx=lowx,则栈中从 x 到栈顶的所有节点构成一个 SCC。

SCC 的缩点:在找出了所有的 SCC 后,枚举原图中的所有边 (u,v),若 uv 不属于同一个 SCC,则在 u,v 所属的 SCC 之间连一条边。

tarjan 编号:tarjan 编号,为原图缩点后 DAG 的拓扑序反序。

2-SAT

2-SAT:有 n 个变量,每个变量只有两种可能的取值。给定 m 个条件,每个条件都形如「若 ai=paj=q」。求是否存在对 n 个变量的合法赋值,使得 m 个条件均得到满足。

2-SAT 的判定

  • 建立包含 2n 个节点的有向图,ai=0 对应节点 iai=1 对应节点 i+n
  • 建立条件「若 ai=paj=q」在图中的边,令 ai=p 所代表的节点向 aj=q 所代表的节点连一条有向边。
  • 使用有向图 tarjan 算法求出图中所有的强连通分量。若存在一个 i 使得 ai=0ai=1 所代表的节点存在于同一个强联通分量中,则没有合法的赋值方案,否则肯定可以找到一组合法的赋值方案。

2-SAT 求方案

  • 在缩点后 DAG " 自底向上 " 的拓扑序中,若 ai=0ai=1 靠后,则 ai=1ai=0
  • tarjan 得到的 SCC 编号,即为缩点后 DAG " 自底向上 " 的拓扑序。

F - 图论 二分图

二分图:若一张无向图的 n 个节点可以分成 A,B 两个非空无交集合,并且在同一集合内的点之间都没有边相连,那么这张无向图称为一张二分图,A,B 分别称为二分图的左部与右部。

二分图染色

二分图判定定理:一张无向图是二分图,当且仅当图中不存在奇环。

二分图判定定理推论:一张二分图的任意子图为二分图。

二分图路径长度简单性质

  • 一张二分图中,任意两点间路径经过的边数奇偶性确定。
  • 一张连通非二分图中,任意两点间路径经过的边数可以是奇数也可以是偶数。

二分图染色:对整张图进行深度优先遍历,尝试用黑白两种颜色标记图中的节点,当一个节点被标记后,它的所有相邻节点应被标记与它相反的颜色。若标记过程中产生冲突,则说明图中存在奇环。

二分图匹配

匹配:一组边的集合 S,满足任意两条边都没有公共端点。属于 S 的边被称为匹配边,否则被称为非匹配边。若存在 S 中的一条边的端点为该点,则称该点为匹配点,否则称该点为非匹配点。

最大匹配:包含边数最多的一组匹配。

增广路:若二分图中,存在一条连接两个非匹配点的路径,使得非匹配边和匹配边在该路径上交替出现,则称该路径是匹配 S 的增广路,也叫交错路。满足

  • 长度 len 为奇数。
  • 路径上第 1,3,5,,len 条边为非匹配边,路径上第 2,4,6,,len1 条边为匹配边。

增广路的简单性质:若将增广路上所有边的状态取反,得到的新的边集 S 仍然是一组匹配,并且匹配边数加一。故二分图的一组匹配 S 是最大匹配,当且仅当图中不存在 S 的增广路。

完美匹配:给定一张二分图,其左、右部分别为 X,Y,若最大匹配包含 min(|X|,|Y|) 条匹配边,则称该二分图具有完备匹配。

多重匹配:给定一张二分图,其左、右部节点数分别为 nl,nr。从中选出尽量多的边,使第 i(1inl) 个左部节点至多与 kli 条选出的边相连,第 j(1jnr) 个右部节点至多与 kri 条选出的边相连。

二分图最大匹配:匈牙利算法

匈牙利算法:初始时,所有边都是非匹配边。匈牙利算法不断寻找增广路,依次给每个左部节点 x 寻找一个匹配的右部节点 y,需要满足以下两个条件之一

  • y 是非匹配点。则 xy 构成一条长度为 1 的增广路。
  • y 与左部点 x 匹配,但从 x 出发能找到另一个右部点 yx 匹配。则 xyxy 构成一条增广路。

匈牙利算法原理:一个节点成为匹配点后,至多因为找到增广路而更换匹配对象,但是绝对不会再变回非匹配点。本质上是贪心。

匈牙利算法,时间复杂度O(nm)

匈牙利算法求字典序最小的最大匹配:考虑匈牙利算法的流程,是一个左部节点不断地挤掉右部节点已匹配的左部节点的过程。可以考虑按编号从大到小加入左部节点,将左部节点的所有出边从小到大排序,保证优先考虑较小的右部节点,即可求得字典序最小的最大匹配。

二分图最大匹配:最大流模型

最大流模型:将源点向左部所有点连一条容量为 1 的边,将右部所有点向汇点连一条容量为 1 的边。将左部向右部的连边容量设为 1。此时该网络的最大流即为最大匹配。

最大流模型,时间复杂度:使用 Dinic 算法求最大流,时间复杂度为 O(mn)

二分图最大带权匹配:KM 算法

  • 待填

二分图最大带权匹配:费用流模型

费用流模型:将源点向左部所有点连一条容量为 1 费用为 0 的边,将右部所有点向汇点连一条容量为 1 费用为 0 的边。将左部向右部的连边容量设为 1 并保持费用不变。此时该网络的最大费用最大流即为最大匹配。

二分图最大多重匹配:最大流模型

最大流模型:将源点向左部的节点 i(1inl) 连一条容量为 kli 的边,将右部的节点 j(1jnr) 向汇点连一条容量为 kri 的边。将左部向右部的连边容量设为 1。此时该网络的最大流即为最大多重匹配。

二分图常用模型

点覆盖:一组点的集合 S,满足任意一条边都至少有一个端点属于该点集。

边覆盖:一组边的集合 S,满足任意一个点都至少有一条邻边属于该边集。

独立集:一组点的集合 S,满足该点集中的点两两没有边。

:一组点的集合 S,满足该点集中的点两两有边。

二分图中的最小点覆盖(König 定理)在二分图中,最小点覆盖等于最大匹配

König 定理证明:对于同一个二分图的任意一个匹配,由于匹配中的边的端点不相交,则匹配中的任意一条边至少有一个端点要在点覆盖中,即任意匹配 任意点覆盖。现在考虑对最大匹配构造一个点覆盖

  • 对二分图求一个最大匹配。
  • 从左部每个非匹配点出发,再执行一次 DFS 寻找增广路的过程(一定会失败,以匹配边结束),标记路上经过的所有点。
  • 左部未被标记点,右部标记点,就得到了一组点覆盖。

上述构造,对点覆盖所包含点数等于最大匹配所包含边数的讨论:

  • 左部非匹配点一定都被标记。因为他们是出发点。
  • 右部非匹配点一定都没被标记。否则就找到了增广路。
  • 一对匹配点要么都被标记,要么都没被标记。因为在找增广路的过程中,左部匹配点只能通过右部到达。

由于在上述构造中,我们取了左部未标记点,右部标记点。根据对点的讨论可以发现,恰好是每条匹配边取了一个点,所以选出的点数等于最大匹配所包含的边数。

上述构造,对点覆盖合法性的讨论:

  • 匹配边一定被覆盖。因为恰好有一个端点被取走。
  • 连接两个非匹配点的边一定不存在。否则就有长度为 1 的增广路了。
  • 连接左部非匹配点 i 与右部匹配点 j 的边。j 一定被访问,因为 i 是出发点,而我们取了所有右部标记点,因此这样的边也被覆盖。
  • 连接左部匹配点 i 与右部非匹配点 j 的边。i 一定没有被访问,否则再走到 j 就找到了增广路,而我们取了所有左部未被标记点,因此这样的边也被覆盖。

二分图中的最大独立集在二分图中,最大独立集与最小点覆盖互补

二分图中的最小边覆盖在二分图中,若不存在独立点,则最小边覆盖等于最大独立集

无向图中的最大团在无向图中,原图的最大团等于其补图的最大独立集

有向无环图中的最小不相交路径覆盖在有向无环图 G=(V,E) 中,原图 G 的最小不相交路径覆盖等于 |V| 减去其拆点二分图 G0 的最大匹配

  • 构造拆点二分图 G0,其左、右部节点数均为 |V|,若 (x,y)E,则在左部点 x 与右部点 y 之间连边。

Hall 定理

Hall 定理:一张二分图存在完备匹配,当且仅当对于 1k|X|,均满足从 X 中选出 k 个不同点,连向 Y 的点集大小 k

Trick

树上最大独立集

  • 先选上所有叶子,然后从叶子向上考察每个点能否进入独立集,能选则选。

F - 图论 网络流

网络基础

网络流图

  • 源点:有且仅有一个点 s,它的入度为 0,称这个点为源点。
  • 汇点:有且仅有一个点 t,它的出度为 0,称这个点为汇点。
  • 容量:每一条有向边,均有流量的上限,即容量。

容量函数 cV×VR 的函数,满足

(u,v)E,c(u,v)0(u,v)E,c(u,v)=0

流量函数 fV×VR 的函数,满足以下条件

  • 容量限制:(u,v),f(u,v)c(u,v)
  • 斜对称性:(u,v),f(u,v)=f(v,u)
  • 流守恒性:从源点流出的流量等于汇点流出的流量,即

xV{s,t},(u,x)Ef(u,x)=(x,v)Ef(x,v)

xV{s,t},(x,y)f(x,y)=0

饱和弧 / 非饱和弧:在一个可行流中,若一条边的流量等于容量,则称这条边为饱和弧。否则称这条边为非饱和弧。

零弧:在一个可行流中,若一条边的流量为 0,则称这条边为零弧。

前向弧 / 后向弧:在一个可行流中,对于一条 st 的路径,与路径方向相同的边称为前向弧。否则称为后向弧。

剩余容量函数 cfcf(u,v)=c(u,v)f(u,v)

残量网络 GfGf=(Vf=V,Ef={(u,v),cf(u,v)>0})

整张网络的流量 |f||f|=vf(s,v)

最大流

增广路:残量网络上 st 的路径,前向弧都是非饱和弧,后向弧都是非零弧。

EK

EK

  • 每次在当前流 f 的残量网络 Gf 上,用 BFS 找到一个最短增广路 (x1=s,x2,,xk1,xk=t),将增广路描述成一个流函数 f0

    • 对于 1i<k

    f0(xi,xi+1)=+min1j<k{cf(xj,xj+1)}f0(xi+1,xi)=min1j<k{cf(xj,xj+1)}

    • 而其余函数值为 0
  • 得到一个流量更大的流函数 f=f+f0

  • 不断重复此过程,直到当前流 f 的残量网络 Gf 上不存在增广路。

EK 时间复杂度O(nm2)

EK 时间复杂度证明

  • 每次寻找的增广路长度是不降的。
    • 更强结论:vV,d(s,v)d(s,v)
  • 增广次数:O(nm)
    • 每次增广时,cf(u,v) 最小的边记作关键边。一条边成为关键边的次数至多为 n12

Dinic

Dinic:本质和 EK 相同,但优化了寻找增广路的过程。

  • 分层图优化:Dinic 算法首先对图进行一次 BFS,然后在 BFS 生成的分层图中进行多次 DFS。这样就切断了原图中许多不必要的连接,可以进行多路增广,减少了调用增广函数的次数。
  • 不完全 BFS 优化:在 BFS 到汇点 t 之后就可以停止了,因为后面的路径一定更长。
  • 当前弧优化:每次 DFS 完,找到容量最小的一条边。在这条边之前的路径容量 这条边的容量,可能会引出其他的增广路。这样的话,在找到第一条增广路后,回溯到容量最小边的起点时,可以避免继续枚举已经流满的容量最小边。
  • 点优化:在同一次 DFS 中,如果一个点引发不出任何的增广路,可以将该点在层次图中抹去。

Dinic 时间复杂度O(n2m)

Dinic 时间复杂度证明

  • 在一张分层图上,执行 DFS 的次数最多为 O(m)
  • 建立分层图的次数不超过 n1
    • 每轮增广后,残量网络的 d(s,t) 严格单调递增。

常用模型

限制点的流量:可以考虑将点拆成「入点」与「出点」,从入点向出点连一条有容量的边。

最小割

:在图 G=(V,E) 上,对于某个点集 PV,割 (P,VP) 定义为

(P×(VP))E

割的容量:割包含的边的容量之和,即

c(P,VP)=uPvVPc(u,v)

st:满足 sPtVP 的割。

最大流与最小割在一张网络中,最大流等于最小割

最大流与最小割证明:对于同一个网络的任意一个流 f 和任意一个 st(S,T),均有

|f|=uSvTf(u,v)uSvTc(u,v)=c(S,T)

任意流 任意割。考虑 EK 算法求得的流 f,记流 f 对应的残量网络中从 s 出发可达的所有点组成的点集为 S,不可达的所有点组成的点集为 T,由于找不到流 f 的增广路,故 (S,T) 是一个 st 割,且由残量网络的定义可得 |f|=c(S,T)。故最大流等于最小割。

最小割的可行边(并)与必经边(交)

  • 可行边:一条边 (u,v,w) 是最小割可行边,当且仅当这条边满流,且 Gf 不存在 uv 的路径(u,v 不在同一个强连通分量内)。
  • 必经边:一条边 (u,v,w) 是最小割必经边,当且仅当这条边满流,且 Gf 上存在 suvt 的路径(us 在同一个强连通分量内,vt 在同一个强连通分量内)。

常用模型

二选一模型:有 n 个任务,每个任务可以在机器 A 或机器 B 上完成,花费分别为 aibi。有 m 对二元关系 (xi,yi),若第 xi 个任务与第 yi 个任务不在同一个机器上完成,则增加 vi 的花费。求最小总花费。

  • 模型构造:

    • 建源点 s 与汇点 t,每个任务都建一个点,标号 1n
    • S 向第 i 个任务连一条容量为 ai 的边,第 i 个任务向 T 连一条容量为 bi 的边。
    • 对于每个二元关系 (xi,yi),在第 xi 个任务与第 yi 个任务间连一条容量为 vi 的双向边。
  • 模型分析:

    • i 个任务在机器 A 上完成,就要割去边权为 ai 的边。第 i 个任务在机器 B 上完成,就要割去边权为 bi 的边。
    • 对于每个二元关系 (xi,yi),若 xi,yi 没有被分配到同一个机器,就要割去边权为 vi 的边。

闭合子图:一个有向图 G=(V,E) 的闭合子图,是该有向图的一个子图,且该子图内点集的所有出边都指向该点集。

最大权闭合子图:点权和最大的闭合子图。

最大权闭合子图模型:有 n 个事件,事件发生会带来收益 wiwi 可正可负,一个事件发生的前提是指定的若干事件必须发生。求最优的确定所有事件是否发生的方案,使得收益最大。

  • 模型构造:
    • 建源点 s 与汇点 t,对每个事件都建一个点,标号 1n
    • wi>0,则令 Si 连一条容量为 wi 的边;若 wi<0,则令 iT 连一条容量为 wi 的边。
    • 对于原图中的边,容量设为 +
  • 模型分析:最大权闭合子图 = 正点权和 最小割。
    • 在一个割中割去的边,负权点表示选择,正权点表示不选。
    • 可以证明,在一个割中,已割去的负权点与未割去的正权点组成的子图 W 与原图的闭合子图对应。如果 W 不是闭合子图,出边可能指向已割去的正权点或未割去的负权点。若为前者,则 W 内的流越过了这个割;若为后者,则 W 内的流可以流向汇点。

费用流

EK & Dinic:每次需要扩展一条费用最小的增广路。

posted @   Calculatelove  阅读(243)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示