《算法分析与设计》学习笔记

作业占 20%,期中占 40%,项目(读 Paper,尝试实现或改进)占 40%

Lecture 1:近似最短路

内容:Dijkstra,APASP,近似距离查询。

很多内容 xtq 在 WC2024 上讲过。

最短路问题

δ(s,t) 表示 st 的最短路,满足三角形不等式。

使用斐波那契堆优化的 Dijkstra 的复杂度为 O(m+nlogn)

对于 APSP,Floyd-Warshall 的复杂度为 O(n3)。更优?无向无权图 O(nω)O(n2.38),有向无权图 O(nμ)O(n2.53)。猜想:当边权是 1n 的整数时,不存在 O(n3δ) 的 APSP 算法。

无向无权图 APASP

d(u,v) 为近似距离。

  • stretch k 近似满足 δ(u,v)d(u,v)kδ(u,v)
  • surplus t 近似满足 δ(u,v)d(u,v)δ(u,v)+t

O~(n2.5) surplus 2

准备工作

独立随机以 1k 的概率选中一个点,得到期望大小为 O(nk) 的点集 D。对于度为 d 的点,其有 1(11k)d 的概率和 D 相邻。取 d=cklogn,则概率为 11nc

定理

给定度数 d,可以找到大小为 O~(nd) 的点集 D,满足所有度不小于 d 的点大概率和 D 相邻。

V1 是所有度不小于 n 的点,D1 是大小为 O~(n) 的点集,满足 V1 的每个点和 D1 相邻。

E2 是所有 (u,v) 满足 uV1vV1,则 deg(u)deg(v) 不超过 n|E2|=O(nn)

算法流程

  • 从每个 uD1 跑 BFS 求出 δ(u,v),其中 uD1vV。时间 O(|D1||E|)=O~(n2n)
  • 从每个 uVE2δ(D1×V) 上跑 Dijkstra。时间 O~(n(|E2|+n|D1|))=O~(n2n)

算法的时间复杂度 O~(n2n)

算法分析

  • uD1vD1,则 δ(u,v) 在第一步求出。
  • u,v 最短路径上所有点的度小于 n,则每条边在 E2 上,δ(u,v) 在第二步求出。
  • 若存在度不小于 n 的点 w,则 wwD1 相邻,d(u,v)δ(u,w)+δ(w,v)δ(u,v)+2

通过 D1 把路径上度数较大的点移动到较小的集合内。

O~(n7/3) surplus 2

这个算法还有可以利用的性质:最短路径要么只有 δ(D1×V),要么只有 E2,两部分独立。δ(D1×V) 的部分已经是近似长度,但 E2 的部分求出了精确值,这里还有优化空间。

改改阈值会发生什么?

V1 是所有度不小于 n2/3 的点,则 |D1|=O~(n1/3)。算法的第一步时间 O~(n7/3),但 |E2|=O(n5/3),无法 Dijkstra。这一步解决了 uv 度不小于 n2/3 或最短路径上有度不小于 n2/3 的点的情况,且 接下来只需考虑边集为 E2 的情况,设新图为 G

再分一层 V2 表示所有度不小于 n1/3 的点,则 |D2|=O~(n2/3)。设 V2 对应 E3,则 |E3|=O(n4/3)。这一步解决了最短路径上所有点度小于 n1/3 的情况(实际上,没有两个相邻的点度均不小于 n1/3 的情况)。

对于路径上有度在 n1/3n2/3 之间的点的情况,设 w 是最后一个这样的点,则 wv 都在 E3 上,存在 wD2w 相邻。我们要求 uw 之间在 G 上的最短路 δ(u,w)。这可以通过从 D2 的每个点 BFS 得到,时间 O(|D2||E2|)=O~(n7/3)

但这样还有一个问题,就是 δ(D2×V) 的大小是 O~(n5/3),不能直接丢进 Dijkstra。设 E 为每个 wV2 和一个邻居 wD2 之间的边集,则 |E|=O(n)。将 E 丢入最终的 Dijkstra,这样就只要求最终能考虑到 δ({u}×D2)。所以从 u 跑 Dijkstra 的时候只要把 δ({u}×D2) 丢进去就行。

算法流程

  • 从每个 uD1 跑 BFS 求出 δ(u,v),其中 uD1vV。时间 O(|D1||E|)=O~(n7/3)
  • 从每个 uD2E2 上跑 BFS 求出 δ(u,v),其中 uD2vV。时间 O(|D2||E2|)=O~(n7/3)
  • 从每个 uVE3δ(D1×V)δ({u}×D2)E 上跑 Dijkstra。时间 O~(n(|E3|+n|D1|+|D2|+n))=O~(n7/3)

通过 D1 把路径上度数较大的点移动到较小的集合内,并删去 E2 以外的所有边。

通过 D2 把路径上度数适中的点移动到较小的集合内,只需保证最后一个度数适中的点被考虑到,并以此减少 Dijkstra 算法的边数。

算法分析

  • uD1vD1,则 δ(u,v) 在第一步求出。
  • u,v 最短路径上所有点的度小于 n1/3,则每条边在 E3 上,δ(u,v) 在第三步求出。
  • w 是路径上最后一个度在 n1/3n2/3 之间的点,wD2(w,w)E。路径 δ(u,w)+δ(w,w)+δ(w,v)δ(u,v)+2 且三部分分别属于 δ({u}×D2)EE3

扩展

分更多层会出现更多中转点,可以做到 O~(kn2+13k4) 的无向无权图 surplus 2(k1) APASP。当 k=O(logn) 时,存在 O~(n2) APASP。

无向无权图 surplus 2 APASP 在 2022 年被邓老师等人改进到了 O~(n2.29)

O~(n2.29) surplus 2

普通 min+ 矩阵乘法(距离乘法)暂无 O(n3δ) 的算法,但 BD 矩阵(只需一个方向的 BD)存在 O~(n2.687) 的距离乘法。

大概思想是观察到 δ(D1×V) 的部分只有两条边,相当于 δ(V×D1)δ(D1×V) 的距离乘法。用欧拉序将矩阵化为 BD,把这部分复杂度变优,就可以更改阈值做到更优复杂度了。

没讲怎么改进 δ(D1×V) 的求解。

分成 O(logn) 层可以进一步做到 O(n2.2593)

O~(n2) (2,1) 近似

δ(u,v)d(u,v)2δ(u,v)+1

算法流程

对每个 0ilog2n,设 Vi 为所有度不小于 n2i 的点,得到大小为 O~(2i) 的覆盖集 Di 和对应的 E。设 Ei 为所有 uVi1vVi1 的边。

  • Di 的每个点在 Gi=(V,EiE) 上跑 BFS 求出 δi(Di×V)。时间 O(|Di|(|Ei|+n))=O~(n2)

ci(u)Gi 上距离 u 最近的 Di 的点。

  • δi(u,ci(u))+δi(ci(u),v)δi(u,ci(v))+δi(ci(v),v) 更新 d(u,v)

算法分析

考虑 u,v 最短路上度数最大的点 x。因为 V0=,所以存在 i 使得 xVixVi1。此外,因为 x 的度数最大,所以路径上所有边都在 Gi 上。设 wDix 相邻且 (w,x)E,则 uxwwxv 都在 Gi 上。

u=ci(u)v=ci(v),于是 δi(u,u)δ(u,x)+1δ(v,v)δ(v,x)+1,不妨设 δi(u,u)δ(u,v)2+1,则

δi(u,u)+δi(u,v)2δi(u,u)+δi(u,v)2δ(u,v)+2

  • 当路径长度是偶数时,如果 x 不在中点,不妨设靠近 u 一侧,那么 δi(u,u)+δi(u,v)2δ(u,v)。如果 x 在中点,那么考虑度数次大的点 x 以及对应的 j,根据 Ej 的定义可知路径上所有边在 Ej 上,此时 x 一定不在中点。
  • 当路径长度是奇数时,δi(u,u)+δi(u,v)2δ(u,v)+1。当 xx 分别是最中间一条边的两端时,不等式可能取等。

为什么无向无权

对于有向图,以上算法显然行不通。

对于带权图,和一个点相邻不一定距离这个点近。可以考虑乘法近似。

无向带权图 APASP

截断 Dijkstra

考虑求出距离一个点最近的 b 个点,普通 Dijkstra 需要 O~(nb) 的时间。截断 Dijkstra 在普通算法上加入改进:只考虑一个点权值最小的 b 条出边。

时间 O~(b2)

O~(n7/3) stretch 3

类似的思想。

B(u) 是距离 u 最近的 n2/3 个点,D 是随机选出的大小为 O~(n1/3) 的点集,满足所有 B(u)D 有交。

这样,从 D 出发跑 Dijkstra,如果 uDvDvB(u),得到最短路。否则存在 wB(u)D。因为 vB(u),所以 δ(u,w)δ(u,v)。同时 δ(w,v)δ(w,u)+δ(u,v)2δ(u,v),所以 δ(u,w)+δ(w,v)3δ(u,v)

显然复杂度为 O~(n7/3)

Cohen-Zwick 在 1997 年做到了 O~(n3/2m1/2) stretch 2O~(n7/3) stretch 73O~(n2) stretch 3(可用 O~(n2) (2,1) 近似解决)。

近似最短路查询

以上讨论给出了使用 O(n5/3) 空间,O~(n7/3) 预处理的 O(1) stretch 3 近似最短路查询。

可以用 O(kn1+1k) 的空间做 O(k) stretch 2k1 近似最短路查询 [Thorup, Zwick, 2001]。

Lecture 2:斐波那契堆

内容:二叉堆、二项树、斐波那契堆。

以下所有内容考虑小根堆:每个点的权值不大于其儿子权值。

二叉堆

堆的结构是一棵完全二叉树。根是最小值,树高 log2n

如何实现?用指针维护父亲和儿子关系,或左儿子两倍右儿子两倍加一。

查询最小值

O(1)

插入

x 插入下一个叶子的位置,向上冒泡。O(logn)

减法

将元素的值减去 k,向上冒泡。O(logn)

删除最小值

将根和最右侧叶子交换,向下冒泡(和较大的儿子交换)。O(logn)

合并

暴力合并。Ω(n)

二项堆

二项树

B0 是一个点,BkBk1 在根底下接一棵 Bk1

性质:

  • |Bk|=2k
  • Bk 深度为 k
  • Bk 的第 i 层有 (ki) 个点。

定义一个 结点的阶 是其儿子个数,一棵 二项树的阶 是其根的阶。

原则:只合并同阶二项树

二项堆

二项堆维护的过程借助了二进制分组的思想保证复杂度:一旦有两棵同阶二项树,则合并。因此,若二项堆的大小为 n,则该二项堆恰含所有 n2 进制下为 1 的位对应的二项树。

一个二项堆最多有 log2n 棵二项树。

合并

模拟二进制加法。O(logn)

删除最小值

找到最小值,删去。对应二项树分裂成若干二项树,与原有二项树合并。O(logn)

减法

向上冒泡。O(logn)

删除

减到 再删除最小值。O(logn)

插入

二进制模拟加 1O(logn),均摊 O(1)

查询最小值

O(logn)

斐波那契堆

斐波那契堆只有删除(最小值)的复杂度为 O(logn)。其余操作均为均摊 O(1)

从空斐波那契堆开始,任何 a1 次插入、a2 次删除和 a3 次减法的操作序列需要 O(a1+a2logn+a3) 时间。

做到 O(1) 插入、删除和减法是不可能的,因为基于比较的排序有下界 Ω(nlogn)。因此,斐波那契堆相当优秀。

其基本想法和二项堆类似,但对结构的要求更宽松。二项堆在每次操作后立刻重构,斐波那契堆采用 懒重构 的思想,直到删除最小值之后再重构。

维护:

  • 一些堆。
  • 根的列表和最小值指针。
  • 结点的标记:表示该结点已经失去了一个儿子。如果再失去一个,则以它为根的子树会被剪下来。

R(x)R(H) 表示阶,T(H) 表示树的个数,M(H) 表示被标记的结点数量。定义势能 Φ(H)=2T(H)+M(H)

定义均摊时间为实际用时加上势能的变化量,则总用时不超过总均摊时间之,因为势能非负且初始为 0。势能可能需要乘以一些常数。

插入

将结点插入根的列表,更新最小值指针。

时间 O(1),势能 +1,均摊 O(1)

合并两棵树

将较大的根连到较小的根下面。

删除最小值

把根的所有子树全部融到根列表,重构使得没有根的阶相同。

时间 O(R(H)+T(H)),势能 O(R(H))T(H),均摊(给势能乘以一定常数)O(R(H))

在只有前述操作时,R(H)=O(logn)

减法

如果堆性质没有被破坏,则直接减。

否则把以 x 为根的树剪下,加入根列表,标记其父亲(除非其父亲为根)。

如果不特殊处理,这一步会扭曲树的形态,导致 R(H) 过大。为了保证树的平整,如果一个点已经被标记两次,则取消标记,并将以该点为根的子树剪下,标记其父亲(除非其父亲为根)。这一步可能递归。

设剪下子树的次数为 c,则时间 O(c),势能 O(1)c,均摊 O(1)

分析

x 的儿子按照连边顺序记为 y1,,yk。当 yi 连向 x 时,R(yi) 等于当时的 R(x)i1。而接下来 yi 最多失去一个儿子。于是 R(yi)i2

Fkk 阶树的最小大小,则 F1=1F1=2Fk=Fk2++F0+1=Fk2+Fk1,这是斐波那契数列。于是 R(H)logϕn

合并

用双向列表维护根列表。

时间 O(1),势能 0,均摊 O(1)

应用

O(m+nlogn) 最小生成树

在 Dijkstra 或 Prim 的过程中使用斐波那契堆,n 次插入,n 次删除和 m 次减法,时间 O(m+nlogn)

O(m+nlogn) 最小生成树

Fredman & Tarjan [1987] 通过限制堆的大小做到了更优的复杂度:考虑结合 Boruvka 和 Prim,从某个点开始,如果堆里有 k 个元素或碰到了当前生成森林,则停止本次 Prim,从另一个未被访问的点开始。一轮过后,将森林里的所有树缩点,则每个点至少 k 条出边,结点数量不超过 2mk

k=22m/n,则一轮复杂度 O(m+nlogk)=O(m)。新的 k=22m/n=222m/n。可知总轮数为 β(m,n)=min{i:log(i)nmn},其中 log(i)n 表示取 ilog

因此,当 m=O(n) 时,时间为 O(mlogn)。一旦存在常数 k 使得 m=nlog(k)n,则时间为 O(m)

目前学术界的 MST

随机算法 O(m) [Karger, Klein, Tarjan 1995]。

确定算法 O(mα(m,n)) [Chazalle 2000]。

最优算法(复杂度仍为 open problem) [Pettie, Ramachandran 2002]。

判定 MST O(m) [Dixon, Rauch, Tarjan 1992]。

Tarjan 老爷子是真牛啊。

Lecture 3:并查集

内容:并查集的复杂度分析。

问题描述

初始 n 个集合 {1},,{n},支持合并两个集合,以及查找某个元素在哪个集合。

并查集是维护不交集合的数据结构,每个集合用一个代表元表示,支持:

  • Makeset(x):新建包含元素 x 的集合。
  • Find(x):查询 x 所在集合的代表元。
  • Union(x, y):若 x,y 处于不同集合,则合并它们所在的集合,删去原有的两个集合。

以下设 n 为元素数量,m 为操作次数。

链表

用链表维护,每个元素指向下一个元素和代表元。

makeset O(1),find O(1),union O(n)

如果不维护代表元指针,则 find O(n),union O(1)

启发式合并

将较短的链表添加在较长的链表后,时间 O(m+nlogn):元素代表元更新,其所在链表长度至少翻倍。

Up-tree

每个点指向其父节点,没有父节点的点为对应集合代表元。

合并可能导致树的深度达到 O(n),使得 find O(n)

按秩合并

将深度较小的树合并到深度较大的树:深度为 k 的树至少有 2k 个点。

将大小较小的树合并到大小较大的树:每个点被合并时,其所在集合大小至少翻倍。

时间复杂度 O(mlogn)

路径压缩

查询时将路径上的每个点都指向代表元。

复杂度分析

重点是分析路径压缩按秩合并的并查集的复杂度。

r(x) 表示 x 的秩,初始为 0r(x) 增加 1 当且仅当 y 合并到 x 上且 r(x)=r(y)。可知阶为 r 的点数为 O(n2r)

因为 union 等价于两个 find 和一个 link,且 makeset 和 link 显然为 O(1),所以只考虑 m 个 find 的均摊时间。

O((m+n)loglogn)

考虑 r(p(x))r(x)。每次查询,最多 O(loglogn) 个点的该值没有翻倍,因为每个这样的点都会让 r(rep(x))r(x) 翻倍。

对于那些翻倍的点,最多发生 O(logr(x))=O(loglogn) 次。

时间为 O((m+n)loglogn)

O(m+nlogn)

T(m,n,r) 表示 n 个点 m 次操作且秩不超过 r 的最大指针赋值次数,显然 T(m,n,r)nr

s 是秩的阈值。

考虑一次 find 从 x 开始,且根为 y

  • r(y)s,则总赋值次数不超过 T(m,n,s)
  • r(x)>s,则总赋值次数不超过 nr2s
  • r(x)s<r(y)
    • r(p(x))s,考虑到每个点的父亲的秩最多一次从不超过 s 变成大于 s,总赋值次数不超过 n
    • r(p(x))>s,每次操作最多一个这样的点,总赋值次数不超过 m+,其中 m+ 表示涉及到阶大于 s 的点的 find 次数,m=mm+

于是

T(m,n,r)T(m,n,s)+nr2s+m++n=T(m,n,r)m(T(m,n,s)m)+nr2s+n=T(m,n,r)T(m,n,s)+nr2s+n

s=logr,则

T(m,n,r)T(m,n,logr)+2nT(m,n,r)2nlogrT(m,n,r)m+2nlogr

O((m+n)α(n))

Ackermann's function

定义

Am(n)={n+1,m=0;Am1(n+1)(1),m1.

分析

对于

T(m,n,r)T(m,n,s)+nr2s+m++n

第二项不超过 T(m+,n2s,r)m++2nlogr2s,于是

T(m,n,r)T(m,n,s)+2m++2nlogr2s+n

s=logr,则

T(m,n,r)T(m,n,logr)+2m++3n

T(m,n,r)=T(m,n,r)2m,则

T(m,n,r)T(m,n,logr)+3n

T(m,n,r)2m+3nlogr

不断重复上述过程,得

T(m,n,r)c(m+n)logcr

logcr 表示取多少次 logc1 可以让 r 变成常数,而

α(n)min{c1logcn3}

因此时间为 O((m+n)α(n)) [Tarjan 1975]。

是否存在更优美的复杂度分析?Tarjan 同时证明了这个算法的时间下界 Ω(mα(n))

复杂度下界分析

略。

对任何并查集,有 Ω(α(n)) word-operations 的下界 [Fredman, Saks 1989]。

Lecture 4:动态树

Splay

μ(x)=log|S(x)|Φ(S)=xSμ(x)

Splay 引理:每个 splay(x, S) 操作需要 3(μ(S)μ(x))+1 的均摊时间。

  • 每个 Zig 不超过 3(μ(S)μ(x))+1
  • 每个 Zig-Zig 和 Zig-Zag 不超过 3(μ(x)μ(x))

证明的 nasty-case 是 μ(x)=μ(x),此时可以证明 μ(x)+μ(y)+μ(z)<μ(x)+μ(y)+μ(z)

动态最优性猜想:CSPLAY(s)=O(n+COPT(s))

LCT

对 link 的要求:vw 不在同一棵树,且 v 是根。

对 delete 的要求:删除树边。

每个结点有 0/1 个偏好的孩子。用 Splay 维护偏好链,每个 Splay 指向父亲。

access 打通 x 到根的路径,模拟即可。

ETT

用 Splay 维护欧拉序。

换根:考虑 r 的任意一次出现,将欧拉序分为 AB,其中 Ar 之前的部分。删除 A 的第一个点,加入 r,然后将 A 放在 B 之后。

换根之后容易做 link 和 cut。

LCT 做链问题比较优秀,ETT 做子树问题比较优秀。

Lecture 5:动态连通性

完全动态连通性

加边删边查询连通性。想法:维护生成森林。

加边容易,但删树边时需要找到重新连接两部分的边。

每条边有只会增加的等级 le,设 Ei 为等级不小于 i 的边,则 E0E1Elmax

维护 Ei 的生成森林 Fi,满足

  • (u,v)Ei 是非树边,则 u,vFi 上连通(生成森林极大)。
  • (u,v)Ei 是树边,则 (u,v)Fj(j<i) 上也是树边。
  • Fi 的每棵树的大小不超过 n2i

可知若一条边在 Ei 上是非树边,那么它在所有它在的 Ej 上是非树边。

加入 (u,v) 时,将其加入 E0。若 u,v 连通,则为非树边,否则为树边。

删除 (u,v) 时,在所有 E0l 上删去 (u,v)。若是树边,则删去 (u,v) 会将 Fl 对应的树分裂成 T(u)T(v) 两部分。其中一部分的大小小于原树的一半,不妨设为 T(u),则将 T(u) 加入 Fl+1。然后检查所有和 T(u) 相连的非树边,若不连接 T(u)T(v),则一定在 T(u) 内部,移到下一个等级,否则直接连起来。如果等级 l 没有,那么检查等级 l1,以此类推。

动态子图连通性

忽略所有 log 因子。

每个点有开关状态,支持修改一个点的状态,以及查询两个点能否通过开着的点连通。

维护两个集合 P,Q,初始所有点都在 PQ 为空。P 只会删点。打开一个点时将其加入 Q。每 m2/3 次修改重构一次,所以 Q 的大小不超过 m2/3

用删边维护的方法维护 P 的连通性。称总度数大于 m1/3 的连通块为大连通块,数量不超过 m2/3,否则为小连通块。

维护新图 G,结点包含 QH,其中 H 的每个元素表示 P 的一个大连通块,以及原图连接 Q 以及 QH 之间的边。

如果 Q 的结点可以通过小连通块连通呢?若 u,vG 通过小连通块连通,则将 (u,v) 加入 Γ,其大小为 m4/3。将 Γ 加入 G,则 u,vQ 连通当且仅当它们在 G 上连通。

对于查询:

  • 对于 Q 里的点,logn 查询在哪个连通块。
  • 对于大连通块的点,查询在 G 上表示这个大连通块的点,再查询在哪个连通块。
  • 对于小连通块的点,找一个 Q 里的点与其相邻。若不存在则孤立。m1/3

对于预处理:

  • GΓ 都需要 m4/3 的时间。
  • m2/3 次修改重构一次,所以均摊到每个修改 m2/3

对于修改:

  • 当加入或删除 Q 的点时,更新 G 的每个点和这个点的连接情况。m2/3
  • 删除小连通块的点时,重新计算相关的 Γ(m1/3)2=m2/3
  • 删除大连通块的点时,按度数之和从大到小记分裂成的连通块为 R1,,Rk
    • 删掉 P 的边的总数为 m,所以每个修改 m1/3
    • 如果 Ri(i2) 是大连通块,则更新 G 需要 deg(Ri) 的时间。deg(Ri) 减半,最多 logm 轮。m1/3
    • 如果 Ri 从大连通块变成小连通块,则更新 Γ。因为只会变一次,所以 m2/3

Lecture 6:最大流

FF

每次找一个增广路。若所有容量是 [0,U] 的整数,则算法在 |f|nU 轮结束。当 U=1 时,时间 nm

整性定理:若网络所有容量都是整数,则存在所有边的流量都是整数的最大流。

EK

选增广路的时候不要随便选。选最大瓶颈路,足够大容量的路,或者最短路。

Capacity Scaling

Δ 为不小于 U 的最大的二的幂。在边权 Δ 的图上找增广路,最多找 O(mΔ) 次,然后将 Δ 除以 2m2logU

需要强多项式算法。

最短路

指边数最少的路径。

考虑最短路分层图,每次删去至少一条边,反边不会出现在分层图上。最多增广 m 次后得到分层图上的阻塞流,最短路增加。m2n

Dinic

不要每次都在分层图上重新找,一次找完即可。n2m

用 LCT 维护分层图的生成树,nmlogn

单位容量最大流

任意图

O(m) 的时间找到阻塞流,因为每条路径上的所有边被立刻删去。

n2/3 轮之后存在相邻两层 ni+ni+12n1/3,剩余流量不超过 n2/3

m1/2 轮之后存在相邻两层 mim1/2,剩余流量不超过 m1/2

mmin(n2/3,m1/2)

无向图

在残量网络上,只有有流量的边有方向。在单位容量无向图上,任何无环流可以被分解为路径。

如果残量网络的最大流为 v,则最短路不超过 nv,因为每相邻两层至少有 2v 个点。

因为最大流不超过 n,所以无环流最多有 nn+nn1++n=n3/2 条边。因此寻找增广路时最多有 n3/2 条有向边。对于无向边,用完全动态连通性维护,BFS 时只需考虑 n3/2 条边。复杂度 O~(n5/2)

Lecture 7:最小割和 k 连通性

全局最小割

有平凡的 nflow 做法,略。

Karger' Algorithm

随机选一条边收缩,只剩两个点时得到割,但不一定是最小割 c。当且仅当割的每条边都没有被收缩时正确。

因为每个点的度数不小于 c,所以边数不小于 nc2。第 i 次选中的概率为 c(ni)c/2=2ni,所以正确率为

n2nn3n12413=1n2

于是复杂度 n4。同时证明了全局最小割的数量 O(n2)

考虑在还剩 n2 个点时停下,此时正确率为 12。在剩下的小图上跑两次。时间

T(n)=2T(n2)+O(n2)=O(n2logn)

正确率

P(n)1(112P(n2))2

P(n)P(n2)14P(n2)2。设 q(k)=4P(k)1,则 q(n)q(n2)+1+1q(n2)

Q(n)q(n) 的上界,则 Q(n)log2n+K。展开递归式,由调和级数得

Q(n)<log2n+1Q(n2)+1Q(n2)++1Q(6)+K=O(logn)

不能用在 s-t 最小割,因为度数下界没有保证。

k 连通性

最简单的一集。

k 边连通:删去少于 k 条边,仍连通。

k 点连通:删去少于 k 个点,仍连通。要求 G 有多于 k 个点。

k 点连通,则 k 边连通。

双连通分量的判定:Tarjan。

耳分解不在考纲内,略。

Lecture 8:原始对偶松弛算法

集合覆盖

一个元素的频率为它所在的集合数量,f 为最大频率。点覆盖是 f=2 的集合覆盖。

集合覆盖写成整数线性规划 IP:对每个 Si,有变量 xi{0,1} 表示是否选择。最小化 i=1kc(Si)xi,要求 i:eSixi1, eUxi{0,1}

松弛成线性规划 LP:0x1。设 LP 的最优解为 x,将 Sj 加入 I 当且仅当 xj1f,则 I 是集合覆盖且是 f-近似。

jIc(Sj)jIc(Sj)xjffjc(Sj)xjfOPT

LP 的最优解显然不劣于 IP 的最优解。

线性规划

最小化 cTx,要求 Axbx0

LP 算法的复杂度,其中 L 是输入的比特数:

  • Simplex:指数,但很快。
  • Ellipsoid:O~(n6L2)
  • Interior Point:O~(n3.5L2)

Open Problem:是否存在强多项式的算法。

对偶:最大化 bTy,要求 ATycy0

i[1,m], j=1naijxjbi

根据 yi0

i[1,m], yij=1naijxjyibi

j=1nxji=1myiaiji=1myibi

i=1myiaijcj

所以

j=1nxjcji=1myibi

LP-duality Theorem

若原始线性规划问题的最优解空间有限,则其对偶问题的最优解空间有限。若 xy 最优,则

j=1ncjxj=i=1mbiyi

证明略。

Complementary Slackness Conditions(互补松弛条件)

x,y 最优当且仅当:

j, xj=0i=1maijyi=cj

i, yi=0j=1naijxj=bi

根据 j=1nxjcji=1myibi 的证明过程和 LP-duality Theorem 易得。如果条件不满足,自然无法取等。

对集合覆盖,xj=1i=1maijyi=cj,所以每次选一个 ye 增加,直到满足某个 eSkye=c(Sk),此时将 Sk 加入 I。这样每个点都被覆盖,否则其对应的 ye 还能增加。同时解为 f-近似:

SjIc(Sj)=SjIeSjyefeSjyefOPTLPfOPTIP

这是纯组合的算法,无需求解 LP。

posted @   qAlex_Weiq  阅读(2657)  评论(11编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示