北航 · 离散数学 2 · 第十章 图论 · 第十一章 图的基本问题
图论第十、十一章精讲
对应你上传的四份课件,从"图是什么"一直讲到第十一章的欧拉图和哈密顿图。每个概念按 定义原文 → 说人话 → 画出来 → 例题 的顺序讲,关键处有可以动手点的小实验。
这一章只研究一个对象:G = ⟨V, E⟩。V 是点的集合,E 是边的集合。后面所有概念(度、同构、子图、矩阵、通路)都是在问同一类问题:这两个集合之间满足什么条件。抓住这一点,几十个定义就不再是零散的名词。
怎么读课件里的逻辑式
课件几乎每个定义下面都有一行带 ∀ ∧ → ⇔ 的式子。那一行就是定义本身,比中文描述更精确。读法很固定:
| 符号 | 读作 | 例子 |
|---|---|---|
| ∀u∀v( … ) | 对所有的 u、v,括号里都成立 | ∀u∀v((u,v)∈E → u|v):只要 (u,v) 是边,u 和 v 就邻接 |
| A → B | 如果 A,那么 B | (u,v)∈E → u∈V ∧ v∈V:边的两个端点必须在点集里 |
| A ⇔ B | A 当且仅当 B(两者等价) | Gs ⊆ G ⇔ Vs ⊆ V ∧ Es ⊆ E |
| |S| | 集合 S 的元素个数 | |V| = n 就是有 n 个点 |
课件里的 Python 代码也是同一个思路:V 用集合存点,E 用元组列表存边,isgraph(V,E) 就是把上面那条 "端点必须在点集里" 逐条边检查一遍。看代码时把它当成"定义的可执行版本"即可。
- 10.1引言七桥问题、复杂度,了解即可
- 10.2图、邻接与度握手定理是全章第一个核心工具
- 10.2同构怎样判断"两张图其实是一张"
- 10.3特殊图Kn、Cn、Wn、Km,n、Qn …
- 10.4子图与补图六种子图的区别,自补图,Turán
- 10.5矩阵表示Ak 数通路、可达矩阵、距离矩阵
- 10.6通路与回路简单/基本、连通、强/单向/弱
- 10.6分支、回路与非循环图竞赛图、W-过程、连通的充分条件
- 10.7割集与圈割点、桥、Tarjan 算法
- 10.8支配集、覆盖集、独立集极小与最小、匹配、点覆盖
- 11.2欧拉图一笔画、Fleury 算法、中国邮递员
- 11.2哈密顿图回溯搜索、Dirac 定理、充分条件
引言:为什么要学图
课件① 第 7–28 页
这部分是动机,考试一般不考细节,记住下面三件事就够了。
- 哥尼斯堡七桥问题(1736,欧拉):能否每座桥恰好走一次再回到家?把 4 块陆地当点、7 座桥当边,问题变成"图里有没有一条经过每条边恰好一次的回路"(欧拉回路)。结论:连通无向图有欧拉回路 ⇔ 每个点的度都是偶数。七桥图 4 个点的度是 5、3、3、3,全是奇数,所以走不成。这样判断只需看一遍所有点,复杂度 O(|V|);枚举 7 座桥的顺序要 7! = 5040 种。
- 哈密顿图问题:是否存在经过每个顶点恰好一次的回路?看起来只是把"边"换成"点",难度却天差地别:它是 NP 完全问题,目前没有已知的多项式算法。20 个点暴力枚举要 20! ≈ 2.4×1018 种排列。
- 复杂度分级:多项式 O(na) ≪ 指数 O(2n) ≪ 阶乘 O(n!)。后面讲"同构"时还会用到这个视角:判断同构如果去试所有点的对应方式,就是 O(n!)。
课件里 Google 图计算(Pregel)、图神经网络、知识图谱那几页,是在说明图模型的应用面,属于拓展阅读。
图的基本概念、邻接与度
课件① 第 29–53 页
无序偶与有序偶
一切从"两个点怎么配成一对"开始:
- 无序偶 (x, y):不分先后,(a, b) = (b, a)。用来表示无向边。
- 有序偶 ⟨x, y⟩:分先后,⟨a, b⟩ ≠ ⟨b, a⟩。用来表示有向边(从 x 指向 y)。
设 V 是非空顶点集合,E 是边集合,则有序偶 G = ⟨V, E⟩ 称为图。E 由无序偶构成时叫无向图,由有序偶构成时叫有向图。
注意 G = ⟨V, E⟩ 这个尖括号是"图这个整体是一个有序对(先写点集再写边集)",跟边是不是有向无关。
g 不与任何点相连,是孤立点
a⇄e、d⇄e 是方向相反的两条边
必须分清的几个术语
| 术语 | 意思 |
|---|---|
| 自环(环、自圈) | 两端是同一个点的边,如 (c, c) |
| 平行边(多重边) | 两点之间不止一条边(有向图里要求方向也相同) |
| 简单图 | 既没有自环、也没有平行边的图。课件里很多定理(例如"必有两点度相同")只对简单图成立 |
| 孤立点 | 不和任何边关联的点 |
| (n, m) 图 | |V| = n,|E| = m。点数 n 叫图的阶(定义 10.2.3) |
| 权图 | 每条边带一个数(权值 w),边写成三元组 (w, u, v)(定义 10.2.4)。常用"权矩阵"存,不相连处记 ∞,自己到自己记 0 |
三种"挨着"的关系:邻接、关联、相邻
图里只有两种东西(点和边),两两配对就有三种关系,课件用同一个竖线符号 | 表示:
| 谁和谁 | 名称 | 条件 | 记号 |
|---|---|---|---|
| 点 — 点 | 邻接(定义 10.2.5) | 之间有边 (u,v)∈E | u | v |
| 点 — 边 | 关联(定义 10.2.6) | 点是这条边的端点 | u | e |
| 边 — 边 | 相邻(定义 10.2.7) | 两条不同的边共用一个端点 | e0 | e1 |
对照这张图:v1|v2(有边 a),v3|v3(自环 c 让 v3 和自己邻接);v2|f(v2 是 f 的端点);a|g(a、g 共用 v1),d|h(共用 v4)。
度:一个点"挂着"几条边
无向图中与点 u 关联的边数叫 u 的度,记 d(u)。自环算 2 次。
上图里:d(v1)=2,d(v2)=4,d(v4)=3,d(v5)=2,而 d(v3)=5:边 g、b、d 各贡献 1,自环 c 贡献 2。
以 u 为终点的边数叫入度 di(u)(i = in),以 u 为始点的边数叫出度 do(u)(o = out)。度 d(u) = di(u) + do(u)。
握手定理
设 G = ⟨V,E⟩ 是 (n, m) 图,则
即:所有点的度加起来,等于边数的 2 倍。
一句话证明:每条边有 2 个端头,每个端头给某个点的度贡献 1。所有点的度之和就是在数端头总数,也就是 2m。名字的由来:一群人握手,每次握手两个人各记一次,所有人记的次数加起来必然是握手次数的两倍。
课件的归纳证明(对边数 m 归纳):m=1 时成立。假设 m=k 时成立,再加一条边 e,度数和增加 2,不管 e 是连接两个旧点、引入一个新点还是引入两个新点(课件分了 n′=n, n+1, n+2 三种情况),都有 2k + 2 = 2(k+1)。
- 度为奇数的点有偶数个。因为总和 2m 是偶数,偶数度的点加起来是偶数,那奇数度点的度之和也必须是偶数,奇数个奇数相加是奇数,所以奇数度点只能有偶数个。
- 有向图:∑ di(u) = ∑ do(u) = m(每条边恰有一个起点、一个终点)。
- 给你一串"度数序列",先看和是不是偶数,奇数就直接不可能。例如 (3, 2, 2, 1, 1) 和为 9,不存在这样的图。
展开解答(建议先自己想一分钟)
思路是抽屉原理:n 个点放进少于 n 个"度数抽屉",必有两个点落进同一个抽屉。
简单图里每个点最多和其余 n−1 个点相连,所以度只能取 0, 1, …, n−1,共 n 种值,正好等于点数,不能直接用抽屉原理。关键观察:0 和 n−1 不能同时出现。度为 n−1 的点和所有点相邻,那就不会有度为 0 的孤立点。分三种情况:
- 孤立点 ≥ 2 个:它们度都是 0,结论直接成立。
- 孤立点恰好 1 个:其余 n−1 个点不和它相连,最大度只能到 n−2,度取值范围 {1, …, n−2} 只有 n−2 种,n−1 个点放进 n−2 个抽屉,必有两个相同。
- 没有孤立点:度取值 {1, …, n−1},n−1 种值,n 个点,必有两个相同。
展开解答
建模:6 个人是 6 个点,认识就连边。要证:图里没有三角形 ⇒ 有三个点两两不相邻。
盯住一个人 A,其余 5 人分成"A 认识的"和"A 不认识的"两组,必有一组 ≥ 3 人(5 个人分两组,抽屉原理)。
- A 认识至少 3 人,设为 C、D、E。如果 C、D、E 中有两人认识(比如 C、D),那 A、C、D 三人互相认识,与假设矛盾。所以 C、D、E 两两不认识,找到了。
- A 最多认识 2 人,则至少有 3 人与 A 不认识,设为 C、D、E。它们不可能两两都认识(否则是三角形),所以其中某两人(比如 C、D)不认识,于是 A、C、D 两两不认识。
这就是 Ramsey 数 R(3,3)=6 的证明:6 个点的任意图,要么自己有三角形,要么补图有三角形。
展开解答
一共 8 人。每人最多和 6 人握手(排除自己和配偶),所以答案只能在 0~6 之间。唐先生问了 7 个人,7 个不同的答案只能恰好是 0, 1, 2, 3, 4, 5, 6。
- 握 6 次的人和除配偶以外的所有人都握了手。那么除了他的配偶,每个人至少握过 1 次。所以握 0 次的人只能是他的配偶:(6, 0) 是一对夫妇。
- 把这对夫妇拿掉,剩下每个人的次数都减 1(每人都和"6"握过、都没和"0"握过)。剩下的人回答变成 0,1,2,3,4(对应原来 1~5),同样的推理得 (5, 1) 是一对。
- 再拿掉,得 (4, 2) 是一对。
- 只剩回答 3 的人,他的配偶不在被问的 7 人中,只能是唐先生本人。所以回答 3 的是唐太太。
答:唐太太握了 3 次手。
同构:两张图其实是同一张
课件① 第 54–73 页
设无向图 G = ⟨V,E⟩ 和 G′ = ⟨V′,E′⟩,如果存在双射 f : V → V′,使得
则称 G 与 G′ 同构,记 G ≅ G′。
把 G 的每个点改个名字(f 就是改名规则,一个对一个,不能两个点改成同一个名字,也不能漏),改完之后边集和 G′ 一模一样。至于两张图在纸上画成什么形状,完全不重要。
定义里的"当且仅当"两个方向都要:原来有边的改名后还有边,原来没边的改名后也没边。
课件第 54 页给的双射:u1→v1,u2→v4,u4→v2,u3→v3。逐条验证 G 的 4 条边:
| G 的边 | 改名后 | 在 H 中? |
|---|---|---|
| (u1,u2) | (v1,v4) | ✓ |
| (u2,u4) | (v4,v2) | ✓ |
| (u4,u3) | (v2,v3) | ✓ |
| (u3,u1) | (v3,v1) | ✓ |
两边都是 4 条边,G 的边全部映到了 H 的边,H 也没有多出来的边,所以"⇔"两个方向都满足,G ≅ H。把 H 的 v3、v4 左右交换一下重画,它就是正方形。
有向图的同构(课件第 62 页)同理,只是还要保持方向:⟨u,v⟩∈E ⇔ ⟨f(u),f(v)⟩∈E′。
怎么判断同构:必要条件只能用来"否定"
直接按定义找双射,最坏要试 n! 种对应,太慢。课件说,目前没有"简单而充分"的判定条件,但有一组必要条件。同构的两张图必须满足:
- 点数相同;
- 边数相同;
- 度数序列相同(度数相同的点个数相同)。而且同构映射一定把 k 度点映到 k 度点。
还可以继续加:两个 3 度点相邻吗?有没有三角形?有几个连通块?这些"图的不变量"在同构下都不会变。
必要条件的用法是:只要有一条不满足 ⇒ 一定不同构。反过来,全都满足 不能推出同构。例如六边形 C6 和两个分开的三角形:都是 6 点 6 边、每点度都是 2,但前者连通、后者不连通,不同构。要证明同构,必须把双射写出来并验证。
展开解答
两者都是 5 个点、6 条边,前两个条件都满足,接着比度数序列:
- G:a=2, b=2, c=3, d=2, e=3 → 排序后 (3,3,2,2,2)
- H:a=4, b=2, c=3, d=2, e=1 → 排序后 (4,3,2,2,1)
度数序列不同,所以 不同构。(课件第 57 页 H 的边集文字少写了 (a,d),按图应有 6 条边;就算按 5 条边算,边数不同也直接不同构。)
展开解答
两张图都是 6 点 9 边,每个点度都是 3,三条必要条件全部满足,光看这些判不出来。
换一个不变量:三角形。图③里本来就有三角形;图①中,把 1、3、5 放一组,2、4、6 放一组,会发现每条边都连接两组之间(它其实是 K3,3),组内没有边,所以不可能有三角形(三角形必有两个点在同一组)。有三角形的图和没有三角形的图不可能同构,所以 ① ≇ ③。图② 也是 K3,3 的另一种画法,① ≅ ②。
展开解答
(1) 先用握手定理限制度数序列:4 个点度数和为 2×3=6,简单图每个点度 ≤ 3,奇数度的点有偶数个。把 6 拆成 4 个这样的数,只有三种:
每种度数序列恰好只有一种画法,所以一共 3 个。课件追问的 (3,3,0,0) 为什么不行:简单图中度为 3 的点要和另外 3 个点全部相邻,两个这样的点会让其余两个点度数至少为 2,不可能是 0。
(2) 3 个点、2 条有向边,总度数 4,每点出度、入度都 ≤ 2。按"两条边的位置关系"分类:
前三个度数序列都是 (2,1,1),但入度、出度的分布不同(课件写的入度列 0,1,1;0,2,0;1,0,1),所以互不同构;第四个度数序列是 (2,2,0)。共 4 个。
同胚与同态(了解)
同胚(定义 10.2.11):如果 G′ 是在 G 的边上"插入若干新点"(把一条边 (u,v) 换成一条路 u–w0–…–v)得到的,就称 G′ 是 G 的同胚图。插入的点度都是 2,图的"形状骨架"没变。这个概念后面判断平面图时会用到。
同态(扩展):比同构宽松,只要求有函数 f : V→V′ 把边映成边,不要求一一对应,允许多个点合并成一个。课件例子里 x3、x4 都映到 y3。
Weisfeiler–Lehman 算法:给点"上色"来比较
课件介绍了一个实用的同构检验思路。不去试所有对应方式,而是反复给点重新上色:
- 开始时所有点同一种颜色。
- 每一轮,每个点看"自己的颜色 + 所有邻居颜色组成的多重集",相同的组合给同一个新颜色。第一轮之后颜色其实就等于度数。
- 每轮比较两张图各颜色的点数。只要某一轮对不上,一定不同构;颜色不再细分且两边一直一样,就判"可能同构"。
它的弱点正好是课件说的正则图:每个点度数相同,邻居颜色也相同,颜色永远不会分开。下面可以亲手试:
WL 上色实验
选一对图,点"下一轮",看颜色怎么细分。点旁边的数字是颜色编号。
补充:图同构问题目前既不知道是否属于 P,也不知道是否 NP 完全。Babai 在 2015 年给出了拟多项式时间 2(log n)k 的算法。而"子图同构"(判断 G 里是否含有一个和 H 同构的子图)已被证明是 NP 完全的。
特殊图
课件① 第 75–109 页
这些图之所以"特殊",是因为它们的边有清楚的规律,点数、边数、度数都能直接写出公式。学的时候把三个量对上就行:几个点、几条边、每个点几度,边数都可以用握手定理(度数和 ÷ 2)验算。
平凡图与完全图
n ≥ 2 的简单图,任意两个不同顶点之间恰有一条边。
每个点和其他 n−1 个点相连,所以 Kn 是 (n−1) 次正则图,边数 n(n−1)/2(握手:n·(n−1) = 2m)。这也是 n 阶简单图边数的上限。课件第 99–101 页的计时表说明:Kn 的边数随 n 平方增长,n = 5000 时已有约 1250 万条边。
圈图与轮图
Cn:n 点、n 边,2 次正则。Wn(课件记法,共 n 个点):圈上 n−1 条边 + 辐条 n−1 条,共 2(n−1) 条边;圈上的点度为 3,中心点度为 n−1。
二部图(偶图)与完全二部图
无向图 G 的点集能分成两部分 V = V1 ∪ V2,V1 ∩ V2 = ∅,使得每条边的一端在 V1、另一端在 V2。记作 G = (V1, V2; E)。
Km,n:m+n 个点,mn 条边;左边每点度 n,右边每点度 m(验算:mn + nm = 2mn)。
n 立方体图 Qn
每个串有 n 位,翻转任意一位都得到一个邻居,所以 Qn 是 n 次正则图,边数 n·2n/2 = n·2n−1(Q3:12 条)。它还是二部图:按"1 的个数是奇数还是偶数"分两组,翻一位一定改变奇偶性。
0-1 序列图 Sn(De Bruijn 图)
有 N = 2m 个点,编号 0, …, N−1。对每个 i,令 j = (2i) % N,k = (2i+1) % N,则 ⟨vi, vj⟩ 和 ⟨vi, vk⟩ 都是边。这是有向图。
把编号写成 m 位二进制,2i % N 就是"整体左移一位,丢掉最高位,末尾补 0",(2i+1) % N 是末尾补 1。例如 m=3 时 101 → 010 或 011。
所以边 u → v 意味着"u 的后 m−1 位 = v 的前 m−1 位",一条边恰好对应一个 m+1 位串(课件第 89 页:边 ak 用 4 位二进制表示,前 3 位是起点,后 3 位是终点)。每个点出度 2、入度 2,共 2m+1 条边。
r 次正则图与彼德森图
已经见过的:Kn 是 (n−1) 正则,Cn 是 2 正则,Qn 是 n 正则,Kn,n 是 n 正则。彼德森图是 10 个点、15 条边的 3 次正则图(外五边形 + 内五角星 + 5 条连线),是图论里最常用的反例。
n 阶 r 正则简单图要存在,必须:
- r ≤ n−1(最多和其余所有点相连);
- n·r 是偶数(握手定理:nr = 2m)。
满足这两条时一定能构造出来。
展开解答
(1) n = 7:k=5 时 7×5=35 是奇数,违反握手定理;k=7 时 7 > 6,超过上限。B、D 不成立。k=4 可以(C7 的补图),k=6 就是 K7。
(2) n = 6:6k 总是偶数,只看上限 k ≤ 5。k=4 可以,k=5 是 K6,C、D 不成立。
六阶 4-正则图有几个?看它的补图:每个点在 K6 里度为 5,删掉 4 条后剩 1,补图是 1-正则图,也就是 3 条互不相交的边(完美匹配)。课件第 129 页正是从 K6 中删掉三条互不相交的红边。不管删哪 3 条,得到的图都同构(都是八面体图),所以在同构意义下只有 1 个。如果顶点带标号、算不同的边集,则有 5×3×1 = 15 种。
子图、补图
课件① 第 111–134 页
六个定义,全部都是在 Vs、Es 上加不同的条件。先看总表,再逐个看。
| 名称 | 点集条件 | 边集条件 | 一句话 |
|---|---|---|---|
| 子图 Gs ⊆ G | Vs ⊆ V | Es ⊆ E | 拿一部分点、一部分边(边的端点要在 Vs 里) |
| 真子图 Gs ⊂ G | Gs ⊆ G,且 Vs ⊂ V 或 Es ⊂ E | 至少少了点什么,不能是 G 本身 | |
| 生成子图 | Vs = V | Es ⊆ E | 点一个不少,只删边 |
| 导出子图 G[Vs] | Vs ⊆ V | Vs 内部的边全部保留 | 只选点,边被点"导出" |
| 补图 ~G | V | E(Kn) − E | 原来没有的边都连上,原来有的都去掉 |
| 相对补图 G − G1 | E2 的端点 | E − E1 | 从 G 里拿掉 G1 的边 |
若 Vs ⊆ V 并且 Es ⊆ E,称 Gs 是 G 的子图。若再满足 Vs ⊂ V 或 Es ⊂ E(真包含),称为真子图。
隐含要求:Gs 自己也得是个图,所以 Es 里每条边的端点都要在 Vs 中。不能删掉一个点却留下连着它的边。
选定点集 Vs ⊆ V,边集取 E 中两端都在 Vs 里的所有边,得到的子图叫 Vs 导出的子图。
课件第 116 页的式子写成了 "v ∈ Es",应为 v ∈ Vs,是笔误。
G 为 n 阶无向简单图。以 V 为点集,以"使 G 成为完全图 Kn 需要添加的边"为边集,得到的图叫 G 的补图,记 ~G(也常写 Ḡ)。
直接推论:|E(G)| + |E(~G)| = n(n−1)/2;dG(v) + d~G(v) = n−1。
G1、G2 都是 G 的子图,若 E2 = E − E1,且 V2 是 E2 中边关联的点的集合,则称 G2 是 G1 相对于 G 的补图,记 G2 = G − G1。
补图是"相对于 Kn"的特例,相对补图把 Kn 换成任意的 G。注意 V2 只保留还连着边的点。
子图实验
点击顶点或边来选取 Vs、Es,右边实时判断它属于哪几类子图。选一条边会自动选上它的两个端点;取消一个点会顺带取消连着它的边。
解答
G 与 ~G 合起来正好是 Kn,所以 |E(G)| + |E(~G)| = n(n−1)/2。同构的图边数相同,因此
边数是整数,所以 4 | n(n−1)。n 和 n−1 是相邻整数,一奇一偶,奇数那个不含因子 2,所以 4 必须整个整除偶数那个:4 | n 或 4 | n−1,即 n = 4i 或 n = 4i+1。
例子:4 阶的路 P4,5 阶的 C5(课件第 133 页把 K5 拆成五边形和五角星,两者都是 C5)。
注意这只是必要条件:n=4、5 存在自补图,并不是说所有 4 阶图都是自补图。
解答
对 n 做数学归纳。n ≤ 3 时直接验证(n=3 最多 2 条边,⌊9/4⌋=2)。设 n = k 时成立,看 n = k+1 的无三角形图 G。
第一步:G 里一定有一个点的度 ≤ ⌊(k+1)/2⌋。(课件直接用了这个结论,这里补上理由。)反证:假设所有点的度都 > (k+1)/2。任取一条边 (u,v),则 d(u) + d(v) > k+1,而 u、v 的邻居都在这 k+1 个点里,由抽屉原理 u 和 v 必有公共邻居 w,于是 u、v、w 构成三角形,矛盾。
第二步:删掉这个点 x,剩下 k 阶图仍无三角形,由归纳假设最多 ⌊k²/4⌋ 条边,再加回 x 的边:
- k 偶数:k²/4 + k/2 = (k²+2k)/4 = ⌊(k+1)²/4⌋
- k 奇数:(k²−1)/4 + (k+1)/2 = (k+1)²/4
两种情况都 ≤ ⌊(k+1)²/4⌋,结论成立。
上界能取到:完全二部图 K⌊n/2⌋,⌈n/2⌉ 没有三角形(二部图无奇圈),边数正好 ⌊n/2⌋·⌈n/2⌉ = ⌊n²/4⌋。
图的矩阵表示
课件① 第 136–151 页,课件② 第 1–14 页
把图写成矩阵有两个好处:计算机能存,也能用矩阵运算回答图的问题(两点之间有几条长度为 k 的通路?谁能到达谁?最短距离是多少?)。这一节的主线是:邻接矩阵 A → Ak → 可达矩阵 R → 距离矩阵 D。
先说存储:为什么需要稀疏格式
邻接矩阵是 n×n 的。100 万个点就是 1012 个元素,每个按 int64 占 8 字节,约 8×1012 字节 ≈ 7.28 TB。可真实网络很稀疏,绝大多数元素是 0,所以只存非零元素。课件第 142–144 页用下面这个矩阵演示了三种格式:
| 格式 | 数组 | 说明 |
|---|---|---|
| COO | value =[1 1 2 3 1 4 2] row =[0 0 1 2 2 3 3] column =[0 2 2 0 1 1 3] | 每个非零元素记 (行, 列, 值) 三元组,最直观 |
| CSR | value =[1 1 2 3 1 4 2] column =[0 2 2 0 1 1 3] row_ptr=[0 2 3 5 7] | 按行存。row_ptr[i] 到 row_ptr[i+1] 是第 i 行的元素在 value 中的范围,例如第 2 行是下标 3、4,即值 3、1 |
| CSC | value =[1 3 1 4 1 2 2] row =[0 2 2 3 0 1 3] col_ptr=[0 2 4 6 7] | 按列存,与 CSR 对称。元素要按列重新排序 |
课件把 CSR 的行指针也叫 row_index,容易和 COO 的 row 混淆,看长度区分:指针数组长度是"行数+1"。课件第 144 页手写的 CSC 中 value 和 row 两行与 COO 相同,没有按列重排;按列重排后应是上表的结果,可以自己逐列读一遍验证。图的"邻接表"(课件第 141 页的数组 + 链表)本质上和 CSR 是一回事。
关联矩阵:点 × 边
简单无向图,|V|=n,|E|=m。n×m 矩阵 A = [aij]:点 vi 是边 ej 的端点,则 aij = 1,否则为 0。
读法:每一列恰有两个 1(一条边两个端点);每一行的和是这个点的度。所有元素之和 = 2m,这就是握手定理的矩阵版。
边 ej 从 ui 出发,aij = 1;ej 指向 ui,aij = −1;否则 0。
读法:每列恰好一个 1、一个 −1,列和为 0;某一行中 1 的个数是出度,−1 的个数是入度。例如 d 行:1 出现 3 次(e4、e5、e6 从 d 出发),−1 出现 1 次(e3 指向 d)。
邻接矩阵:点 × 点
n×n 矩阵 A = [aij],(vi, vj) ∈ E 则 aij = 1,否则 0。有向图用 ⟨vi, vj⟩,第 i 行第 j 列表示 从 i 指向 j。有平行边时 aij 记边的条数,有自环时对角线非 0。
从邻接矩阵能直接读出什么(课件② 第 6–7 页)
- 无向图的 A 是对称矩阵;有向图一般不对称。
- 没有平行边 ⇔ 元素只有 0 和 1;有自环 ⇔ 对角线有非 0 元素;简单图 ⇔ 只有 0、1 且对角线全 0;零图(没有边)⇔ A 是零矩阵。
- 无向图:d(vi) = 2aii + ∑j≠i aij(自环算两次)。简单图就是"第 i 行之和"。
- 有向图:第 i 行之和 = 出度,第 i 列之和 = 入度。
- 图有 k 个连通分支 ⇔ 适当重排点的顺序后,A 变成分块对角矩阵,每块是一个分支自己的邻接矩阵。
核心:Ak 在数通路
(Ak)ij = 从 vi 到 vj 长度为 k 的通路条数(长度 = 经过的边数,点和边都可以重复)。
为什么?看 k = 2:
乘积 ait·atj 等于 1 恰好当 i→t 和 t→j 两条边都存在,也就是"走两步、中间经过 t"。对所有中间点 t 求和,就是长度 2 的通路总数。同理 Ak = Ak−1·A:先用 k−1 步到某个 t,再走一步到 j,归纳即得。
例:路 a – b – c。
(A²)bb = 2:b→a→b 和 b→c→b。(A²)ac = 1:a→b→c。(A²)ab = 0:a 到 b 没法恰好走 2 步。简单无向图里 (A²)ii = d(vi),因为每个邻居都提供一条"去了就回"的长度 2 通路。
可达矩阵
B(A):把 A 中所有非 0 元素改成 1,0 不变。只关心"有没有",不关心"有几个"。
rij = 1 表示 vi 可以到达 vj。
逐项理解:
- Ak 的 (i,j) 非 0 ⇔ 存在长度恰好为 k 的通路。把 k = 0, 1, …, n−1 加起来,非 0 就说明"存在某个长度的通路",即可达。
- 为什么有 I:I = A0,代表走 0 步,规定每个点可达自己(课件② 第 12 页 R(v1) 里包含 v1 自己)。
- 为什么只加到 n−1:10.6 节的定理 10.6.1 会证明,如果 u 能到 v,一定有一条长度 ≤ n−1 的通路(不重复经过点的通路最多 n 个点、n−1 条边)。更长的项不会带来新的"可达"信息。
证明:I 与任何矩阵都可交换(IA = AI = A),所以二项式定理对 I + A 成立:
所有组合数 Cn−1i ≥ 1,A 的元素又都非负,所以右边第 (j,k) 个元素非 0 ⇔ 某个 aijk ≠ 0 ⇔ I + A + ⋯ + An−1 的第 (j,k) 个元素非 0。布尔化后相等。∎
一般矩阵 (A+B)² = A² + AB + BA + B²,只有 AB = BA 时才能合并成 A² + 2AB + B²,二项式定理才能用。课件第 2 页黄框里 "(A+B)n = ∑CniAiBn−i?" 打问号就是这个原因。这里能用,是因为其中一个是单位矩阵 I。课件用归纳法把这个二项式展开重新证了一遍。
另外,课件 Python 里 R=(I+A)**(n-1) 输出的是 [[42, 18, 44 …]] 这样的大数,那是还没布尔化的 (I+A)n−1,非 0 即可达,套一层 B(·) 才是可达矩阵。
还有一处容易看漏:课件第 5 页调用的是 reachabilitymatrix(A,8,2),第三个参数 n 传的是 2,所以算的是 B[(I+A)1],只反映"一步以内能到"。对照输出可以验证:R 的第 0 行 [1,1,1,0,…] 和 I+A 的第 0 行完全一样。要得到真正的可达矩阵,n 应该传点数 8。
距离矩阵
从 v1 可达 v2 时,最短通路的长度叫距离 d(v1, v2);不可达时 d = ∞(约定 ∞+∞=∞,n+∞=∞)。图的直径 = 所有点对距离的最大值。距离矩阵 D = (dij),dij = d(vi, vj)。
说人话:依次算 A0, A1, A2, …,第一次在 (i,j) 处变成非 0 的那个幂次就是距离。
"你和任何一个陌生人之间所间隔的人不会超过六个",用图论的话说就是:把人当点、认识当边,这张社交网络的直径大约是 6。1967 年 Milgram 的连锁信实验、2001 年 Watts 的电子邮件实验(6 万多名志愿者、18 个目标)都发现消息平均经过 5~7 人就能送到。课件第 11 页列的几个真实网络的直径(美国公路网 617、欧洲公路网 62、DBpedia 12、Twitter 8)也说明:社交类网络点很多,直径却很小。
矩阵实验室
左边点格子编辑邻接矩阵(无向图会自动对称;对角线 = 自环),右边自动算出度数、Ak、可达矩阵、距离矩阵和连通性。点击 Ak 里的任意数字,会列出对应的那几条通路。
邻接矩阵 A(点击编辑)
度数
判断
A 的 k 次幂
可达矩阵 R = B(I + A + ⋯ + An−1)
看未布尔化的 (I+A)n−1(课件 Python 输出的就是它)
距离矩阵 D
二部图与邻接矩阵(课件② 第 8–9 页)
设 G 是 n 个点的简单无向图,邻接矩阵为 A。证明:G 是二部图 ⇔ 对任意奇数 k,Ak 的对角线元素全为 0(即 G 没有奇数长的回路)。
(⇒) G 是二部图,点分成 V1、V2,每条边跨两边。从点 i 出发,每走一步就换一边。若 i ∈ V1,走奇数步后一定在 V2,不可能回到 i;i ∈ V2 同理。所以 k 为奇数时从 i 回到 i 的长度 k 通路条数为 0,即 Ak[i,i] = 0。
(⇐) 假设所有奇数 k 都有 Ak[i,i] = 0,即没有奇数长的闭通路。先看一个连通分支,任取其中一点 v,令
- Vo:从 v 出发能用奇数步到达的点
- Ve:能用偶数步到达的点
- 两者不相交:若某点 u 既能奇数步到、又能偶数步到,把"v 奇数步到 u"和"u 偶数步返回 v"(无向图可以原路倒着走)接起来,就是一条从 v 回到 v 的奇数长闭通路,矛盾。
- 两者覆盖整个分支:分支连通,每个点都能从 v 到达,步数不是奇就是偶。
- 每条边跨两边:若边 (x,y) 两端都在 Ve,则到 x 偶数步、再走一步到 y 就是奇数步,y 同时属于 Vo,与 1 矛盾。两端都在 Vo 同理。
每个分支都这样分好,再合并,就得到整张图的二分,所以 G 是二部图。∎
实际判断时只需检查 k = 1, 3, 5, … 到 n 为止:如果有奇数长的闭通路,就一定有长度 ≤ n 的奇数圈。实验室里的"二部图"判断就是这样算的,可以选 C6 和 C5 对比。
通路和回路
课件② 第 16–38 页
通路、简单通路、基本通路
若 uk ∈ V,(uk, uk+1) ∈ E,k = 0, 1, …, n−1,则称点 u0 与 un 之间存在通路,记 u0 ⇒ un。通路的长度是边数 n。
课件的递归写法:(1) 每条边本身是通路;(2) 若 (u0, …, un−1) 是通路且 (un−1, un) ∈ E,则在末尾接上 un 仍是通路。
说人话:沿着边一步一步走出来的点序列就是通路,点和边都允许重复。
简单通路:每条边最多出现一次。
基本通路:每个顶点最多出现一次。
关系:基本通路一定是简单通路(点不重复,边自然不重复:边重复意味着它的端点也重复)。反过来不对。
| 本课件 | 点重复? | 边重复? | 英文常用 | 屈婉玲版教材 |
|---|---|---|---|---|
| 通路 | 可以 | 可以 | walk | 通路 |
| 简单通路 | 可以 | 不可以 | trail | 简单通路 |
| 基本通路 | 不可以 | 不可以 | path | 初级通路(路径) |
课件把定义 10.6.1 叫 "path",但它允许重复,对应的是英文的 walk。做题按本课程的叫法。
通路判定器
在课件第 21 页这张图上输入一串顶点(空格分隔),自动判断它是不是通路、长度多少、是简单还是基本、是否是回路。
G 是 n 阶图。若顶点 u、v 之间存在通路,则存在长度 ≤ n−1 的通路。
证明:设通路为 u = u1 ⇒ u2 ⇒ ⋯ ⇒ um = v。如果它已经足够短就结束。否则它上面的点比 n 个多,由鸽笼原理必有 i < j 使 ui = uj(同一个点出现两次)。把中间绕的那一圈 ui+1, …, uj 剪掉:
仍是从 u 到 v 的通路,而且更短。反复剪,直到没有重复点为止。此时这是一条基本通路,至多 n 个不同的点,所以至多 n−1 条边。∎
- 可达 ⇔ 存在基本通路(课件② 第 10 页的定理)。判断能否到达,只需要找不重复点的路。
- 它就是可达矩阵只加到 An−1 的理由。
回路
回路:从 u 出发并回到 u 的通路,记 u ⇒ u。
简单回路:边不重复的回路。
基本回路:除起点终点重合外,点不重复的回路(就是"圈")。
经过有向图中所有节点的一条通路(回路),称为完备通路(完备回路)。只要求每个点至少经过一次,允许重复。
无向图的连通
无向图中 u、v 之间存在通路,称 u 和 v 连通。任意两个点都连通的图叫连通图,否则是非连通图。连通关系把点集分成若干块,每块叫一个连通分支。
连通无向图中,删掉一个点(及它关联的边)后不再连通,这个点叫割点。删掉一条边后不再连通,这条边叫割边或桥。
直觉:桥是"唯一的通道"。一条边在某个回路上,删掉它还能绕回路另一侧走,就不是桥。所以一条边是桥 ⇔ 它不在任何回路上。
有向图的三种连通
| 名称 | 条件(对每一对点 u、v) | 定义 |
|---|---|---|
| 强连通 | u ⇒ v 并且 v ⇒ u | 10.6.14 |
| 单向连通 | u ⇒ v 或者 v ⇒ u(至少一个方向能到) | 10.6.15 |
| 弱连通 | 基础图是连通的(忽略方向能连上) | 10.6.16 |
| 不连通 | 连弱连通都不是 | 10.6.17 |
强连通 ⇒ 单向连通 ⇒ 弱连通,反方向都不成立(上面后两个图就是反例)。判断时从强往弱试:先看能不能两两互达,再看任意两点是不是至少一个方向能到,最后忽略方向看连不连通。在矩阵实验室里勾选"有向图",判断栏会给出这个结论。
两个定理:用"一条通路"刻画连通性
容易的方向(⇐):有完备通路 w1 ⇒ w2 ⇒ ⋯ ⇒ wt,所有点都在上面。任取两点 u、v,它们在通路上一前一后,前面的沿着通路就能走到后面的,所以至少一个方向可达,G 单向连通。完备回路的情况更强:沿回路绕一圈,谁都能到谁,所以强连通。
强连通 ⇒ 完备回路:把点排成 v1, v2, …, vn,强连通保证每段 vi ⇒ vi+1 和最后 vn ⇒ v1 都有通路,首尾接起来就是一条经过所有点的回路。
单向连通 ⇒ 完备通路(难点):这里不能随便排顺序,因为 vi 不一定能到 vi+1。课件第 30–38 页用的是对点数归纳 + 插入的思路:
- 假设除 v 以外的点已经串成一条通路 v1 ⇒ v2 ⇒ ⋯ ⇒ vn。
- 把 v 插进去。单向连通保证 v 和每个 vi 之间至少一个方向可达。
- 若 v ⇒ v1:把 v 放最前面。
- 若 vn ⇒ v:把 v 放最后面。
- 否则 v1 ⇒ v 且 v ⇒ vn。从左往右找第一个满足 v ⇒ vi 的位置 i(i ≥ 2),那么 vi−1 ⇒ v,于是 ⋯ ⇒ vi−1 ⇒ v ⇒ vi ⇒ ⋯,v 插进了中间。
课件的图就是在演示这个"找插入位置"的过程(红色箭头表示 v 和各点的可达方向)。课件第 37–38 页还处理了一个细节:去掉 v 之后,剩下的图可能不再单向连通(原来的通路可能要经过 v),所以要先把剩下的点分成几段通路,再逐段扩充。
在单向连通图里,"可达"关系有两个性质:任意两点至少一个方向可达,并且可达有传递性(u⇒v,v⇒w 推出 u⇒w)。这样的关系可以把所有点排成一列 v1, …, vn,使前面的总能到后面的(就像比较大小然后排序,每次挑一个"能到达其余所有点"的点放在最前)。然后把 v1⇒v2, v2⇒v3, … 这些通路首尾接起来,就是完备通路。∎
展开解答
从 a 出发:a→b→e→c,e→d,能到所有点。再看其他点能否回到 a:b→a;e→d→a;c→b→a;d→a。每个点都能到 a,a 又能到每个点,所以任意两点都能经过 a 互达,强连通。
完备回路:a → b → e → c → b → a → d → a,经过了全部 5 个点(b、a 重复出现是允许的)。也可以是 a → b → e → c → b → e → d → a。
(续)竞赛图、分支、回路与非循环图
课件③ 第 41–67 页
这一部分在上一节"连通"的基础上继续往下走,回答四个问题:一张不连通的图能拆成几块(分支);什么样的图本身就是一个圈(回路、半回路、有向回路);怎么判断图里有没有圈(W-过程、非循环图);边要多到什么程度图才一定连通(连通的充分条件)。
竞赛图与勒代定理
有向图 G = ⟨V,E⟩,对任意两个不同的顶点 u、v,⟨u,v⟩ ∈ E 或 ⟨v,u⟩ ∈ E,并且恰好只有一个。
名字来自循环赛:每两个选手恰好比一场,u → v 表示 u 赢了 v。把 Kn 的每条边任意定一个方向,得到的就是竞赛图。
课件第 43 页的定义只写了"或者",没有写"恰好一个"。通常的定义要求两点之间只有一个方向(一场比赛只有一个胜者),下面的证明也用到了这一点。
每一个竞赛图都有一条有向哈密顿通路,即一条经过每个顶点恰好一次的有向通路(不要求回到起点)。
它和上一节定理 10.6.3 的关系:竞赛图里任意两点之间都有一条边,当然单向连通,所以由定理 10.6.3 它有完备通路;勒代定理更进一步,说这条通路可以做到每个点只经过一次。
证明(对点数归纳,就是"插队"):1 个点时显然成立。假设前 k 个点已经排成一条有向通路 v1 → v2 → ⋯ → vk,现在加入新点 v,要把它插进队伍里:
- 如果 v → v1:把 v 排在最前面,变成 v → v1 → ⋯ → vk。
- 否则一定是 v1 → v(竞赛图里两点之间恰好一条边)。此时如果 vk → v,把 v 排在最后面。
- 剩下的情况是 v1 → v 而 v → vk。从左往右找第一个满足 v → vi 的位置 i(因为 v → vk,一定找得到,而且 i ≥ 2)。i 是第一个,所以 v 没有指向 vi−1,只能是 vi−1 → v。于是 ⋯ → vi−1 → v → vi → ⋯,v 插在了中间。
每次插入后仍是一条经过所有已加入点、每点一次的有向通路,归纳完成。∎
展开解答
建图:选手是点,"u 没有输给 v"就画 u → v(u 赢 v 就从 u 指向 v;如果是和棋,两个方向都满足"没输",随便定一个方向)。每两人恰好一场,所以这是一个竞赛图。
由勒代定理,存在有向哈密顿通路 v1 → v2 → ⋯ → vn。按这个顺序编号 1, 2, …, n,每条边 vi → vi+1 正好说明第 i 号没有输给第 i+1 号。∎
插队实验
随机生成一场 5 人循环赛(箭头从胜者指向负者),按上面的证明逐个把选手插进队伍,最后的排列就是一条哈密顿通路(橙色)。
部分概念关系图(课件第 41 页)
这张表是这一节的"地图",后面每个概念都能在里面找到位置。每一行的"⟺"表示:图具有左边的连通性,当且仅当它恰好有一个对应的分支。
| 连通性 | ⟺ 分支 | 本身是一个"圈"的图 | |
|---|---|---|---|
| 无向图 | 连通 | 恰有 1 个分支 | 回路(连通 2 度正则图) |
| 有向图 | 强连通 | 恰有 1 个强分支 | 有向回路;基础图是回路的叫半回路 |
| 单向连通 | 恰有 1 个单向分支 | ||
| 弱连通 | 恰有 1 个弱分支 |
极大子图与分支
设 G′ 是 G 的具有某性质 P 的子图,并且对 G 的任意具有性质 P 的子图 G″,只要 G′ ⊆ G″ 就有 G′ = G″,则称 G′ 是 G 相对于性质 P 的极大子图。
极大的意思是"已经不能再扩大了":在保持性质 P 的前提下,再往里加任何点或边都会破坏 P。最大的意思是"在所有满足 P 的子图里规模最大"。
打个比方:一个班的若干个小团体,每个小团体都"不能再拉人进来"(极大),但它们人数可以不一样,人数最多的那个才是"最大"。一张图可以有好几个极大子图,它们大小不同。这个区别在 10.8 节会反复出现。
无向图 G 的极大连通子图称为 G 的分支(连通分支),分支个数记为 W(G)。
有向图 G 的极大强连通子图称为强分支,极大单向连通子图称为单向分支,极大弱连通子图称为弱分支。
(1) 连通无向图恰有一个分支,非连通无向图的分支多于一个。
(2) 强连通(单向连通、弱连通)有向图恰有一个强分支(单向分支、弱分支);否则多于一个。
道理很直接:G 本身连通时,G 就是一个连通子图,而且不能再扩大,所以它就是唯一的分支。
孤立点 4 自己也算一个分支
有向图的三种分支(课件第 47–48 页)
用上一节距离矩阵那张有向图来看:
弱分支只有 1 个,就是整张图(忽略方向后连通)。
- 为什么 {v1,v2,v3} 是强分支:沿着 v1→v2→v3→v1 绕圈,三点两两互达。加入 v4 就不行了,v4 回不到 v3。
- 为什么 {v1,…,v5} 是单向分支:任意两点至少一个方向能到(比如 v1⇒v5,v2⇒v4)。加入 v6 就不行:v6 只能到 v5,v6 和 v1 互相都到不了。
- 为什么 {v5,v6} 也是单向分支:v6⇒v5,而且它已经不能扩大:再加入任何一个点 x ∈ {v1,…,v4},x 和 v6 互相都到不了。
| 结点 | 边 | |
|---|---|---|
| 强分支 | 恰在一个("互达"是等价关系,强分支就是等价类) | 不一定。e4、e5、e6 不在任何强分支里,因为它们两端不能互达 |
| 单向分支 | 至少在一个,可能在多个。v5 同时在两个单向分支里 | 至少在一个(一条边的两个端点本身就单向连通),可能在多个 |
| 弱分支 | 恰在一个 | 恰在一个 |
强分支能把点"分干净",原因是"u、v 互达"满足自反、对称、传递,是一个等价关系。"单向可达"不满足传递性(v1⇒v5、v6⇒v5,但 v1 和 v6 互不可达),所以单向分支会重叠。
展开解答
"划分" {V1, V2} 指:两个都非空、不相交、并起来是 V。所以结论说的是:不管怎么把点分成两堆,总有一条边跨在两堆之间。
充分性(⇐,反证):假设 G 不连通,则 G 至少有两个分支。取其中一个分支 G1,令 V1 = G1 的点集,V2 = V − V1,这是一个划分。分支是"极大"连通子图,所以不可能有边从 V1 连到外面(否则把那条边和那个点加进来仍连通,与极大矛盾)。于是这个划分没有跨边,与条件矛盾。
必要性(⇒):任取 v1 ∈ V1,v2 ∈ V2。G 连通,所以有一条从 v1 到 v2 的路 v1 = u0, u1, …, uk = v2。起点在 V1,终点在 V2,所以沿路走的过程中一定有某一步从 V1 跨到 V2:取第一个落在 V2 的点 uj,则 uj−1 ∈ V1,边 (uj−1, uj) 就是要找的跨边。∎
课件用的是对路径长度归纳:看路上与 v1 相邻的点 v′,若 v′ ∈ V2,边 (v1, v′) 就是跨边;若 v′ ∈ V1,就从 v′ 出发、路径短了一步,由归纳假设得证。两种写法是同一个意思。
回路、半回路、有向回路(作为"图")
上一节定义 10.6.5 的"回路"是一条走法(一个点的序列,可以重复)。这里的"回路"是一种图:这张图本身长成一个圈。两者用的是同一个词,看上下文区分:"G 有一条回路"指走法,"G 是回路"指图。
- 回路:连通的 2 度正则(无向)图。
- 半回路:基础图是回路的有向图(忽略方向是一个圈,箭头方向随便)。
- 有向回路:每个结点的出度和入度都为 1 的弱连通有向图(箭头顺着一个方向绕一圈)。
- 回路(半回路、有向回路)的长度是它的边数。
但顺着箭头绕不回来
为什么"连通"不能省:两个分开的三角形也是 2 度正则图,但它是两个圈,不是一个回路。为什么有向回路要求"弱连通":两个分开的有向三角形每点出入度都是 1,同样要排除。有向回路一定是半回路,反之不然。
设 v 是图 G 的任意结点。G 是回路(或有向回路),当且仅当
(i) G 的阶与边数相等(|V| = |E|),并且
(ii) G 中存在一条从 v 到 v 的回路,除了 v 在其中出现两次(起点和终点)外,其余每个结点和每条边都在该回路中恰好出现一次。
条件 (ii) 说的是:从 v 出发能"一笔画"地把所有点、所有边各走一遍回到 v。
充分性((i)(ii) ⇒ G 是回路):
- 由 (ii),所有点都在一条闭合走法上,任意两点都能沿着它互相到达,G 连通。
- 回路每经过一个点,就"进来一条边、出去一条边",所以每个点的度至少是 2。
- 如果某个点的度大于 2,那么 2|E| = ∑d(v) > 2|V|,与 (i) 的 |V| = |E| 矛盾。所以每点度恰好为 2,G 是连通 2 度正则图,即回路。
必要性(G 是回路 ⇒ (i)(ii)):
- (i):每点度为 2,由握手定理 2|E| = ∑d(v) = 2|V|,所以 |E| = |V|。
- (ii):从 v 出发沿一条边走。到达一个新点时,它有 2 条边,进来用掉一条,还剩一条可以出去,所以不会卡住。也不会第二次走到 v 以外的某个旧点(那需要它有第 3 条边)。点数有限,最终一定回到 v。这样走出的闭合路径上的点和边构成一个连通的 2 度正则子图,它不和其他点相连,而 G 连通,所以它就是 G 的全部。
有向回路的版本相同,把"度为 2"换成"出度、入度都是 1"。课件第 56 页用的是对阶数归纳:在 n+1 阶有向回路里删掉 v,把它前后两点 vn、v1 直接连上,得到 n 阶有向回路(可能出现重边),由归纳假设拿到通路后再把 v 插回去。
有回路与非循环图
(1) 如果回路(有向回路、半回路)C 是 G 的子图,就称 G 有回路(有向回路、半回路)C。
(2) 没有回路的无向图,和没有半回路的有向图,称为非循环图。
如果有向图 G 有子图 G′,使得 G′ 中每个结点 v 都有 doG′(v) > 0(出度为正),则 G 有有向回路。把"出度"换成"入度",结论同样成立。
直觉:在 G′ 里每个点都有路可走(都能出去),从任何点出发一直走,永远不会卡住;但点只有有限个,迟早会走到走过的点,这就绕成了一个圈。
证明(入度版,课件写法):取 G′ 中最长的基本通路 v0 → v1 → ⋯ → vn。v0 的入度大于 0,所以有边 e = ⟨v, v0⟩。如果 v 不在这条通路上,把 v 接在最前面就得到更长的基本通路,与"最长"矛盾。所以 v 就是通路上的某个 vi,于是 v0 → ⋯ → vi → v0 是一条有向回路。∎
反过来读(逆否命题):没有有向回路的有向图,它的每个子图里都至少有一个出度为 0 的点(也至少有一个入度为 0 的点)。W-过程就是靠这一点工作的。
W-过程:判断有向图是否有有向回路
设 v 是有向图 G 中 do(v) = 0 或 di(v) = 0 的结点。从 G 中去掉 v 及与之关联的边,得到 G − {v},这个操作叫一次 W-过程。
- G 有有向回路 ⇔ G − {v} 有有向回路。
- 若 n 阶有向图 G 没有有向回路,则经过 n−1 次 W-过程得到平凡图。
为什么删 v 不影响答案:有向回路上每个点出度、入度都至少为 1。v 的出度或入度为 0,它不可能在任何有向回路上,删掉它不会破坏任何回路,也不会凭空造出回路。
为什么无回路时一定能删到只剩 1 个点:由上面定理的逆否命题,没有有向回路的图里总有出度为 0 的点,所以每一步都有点可删;删完后的子图仍然没有有向回路,可以继续。反过来,如果中途卡住(剩下的每个点出度、入度都大于 0),由定理,图里一定有有向回路。
这就是数据结构课里的"拓扑排序":按删除顺序倒过来排,就得到一个使所有边都从前指向后的顶点顺序。课件说课程选修系统检测先修课是否循环依赖、编译器检测递归调用,用的都是这个方法。
W-过程实验
课件第 60 页的有向图。每次删除一个出度或入度为 0 的点(优先删出度为 0 的)。切换到"看作无向图"可以检查它是不是非循环图;勾选"加一条边 v7→v1"可以看有回路时是怎么卡住的。
判断一个图是否是非循环图(课件第 61 页)
图 G 不是非循环图,当且仅当 G 有子图 G′,使得 G′ 中每个结点都有 dG′(v) > 1(度至少为 2)。
等价地:G 是非循环图,当且仅当 G 的每个子图 G′ 中都存在一个结点 v,使得 dG′(v) ≤ 1。
这里的度对有向图按基础图算(入度加出度)。理由和有向版本一样:在每个点度都 ≥ 2 的子图里,走到一个点总能从另一条边离开,走不到头,迟早绕成圈;反过来,一个圈本身就是每点度为 2 的子图。
判定算法:令 G0 = G。只要 Gi 里有度 ≤ 1 的结点 vi,就令 Gi+1 = Gi − {vi}。得到序列 G0, G1, …, Gm(m ≤ n−1)。如果 Gm 是平凡图,G 是非循环图;否则(卡住了)不是。直观上就是不断"剪掉叶子"。
课件第 61 页的图 (a) 就是 W-过程那张图,它标注"不是非循环图":忽略方向后 v1、v2、v5 构成三角形,这是一个半回路。在上面实验里切到"看作无向图",一个点都删不掉。
连通的充分条件(课件第 62–63 页)
设 G 为 n 阶简单无向图。
(1) 若 G 中任意两个结点的度数之和 ≥ n−1,则 G 连通。
(2) 若 G 中每个结点都有 d(v) ≥ (n−1)/2,则 G 连通。
(1) 的证明:任取两个结点 u、v,证明它们之间有路。
- 如果 u、v 相邻,已经连通。
- 如果不相邻:简单图中,u 的邻居和 v 的邻居都只能在其余 n−2 个点里(不能是自己,也不能是对方)。可是 d(u) + d(v) ≥ n−1 > n−2,两个邻居集合的大小加起来超过了 n−2 个"位置",由抽屉原理它们必有公共元素 w。于是 u–w–v 是一条路。
所以任意两点都连通(而且距离不超过 2)。
(2) 的证明:对任意 u、v,d(u) + d(v) ≥ (n−1)/2 + (n−1)/2 = n−1,由 (1) 得 G 连通。
分支数与边数的关系(课件第 64–67 页)
设 G 为 n 阶简单无向图,有 k 个分支、m 条边,则
先猜边数最多的情形:k 个分支,要让边尽量多,就把点尽量"堆"到一个分支里,并且让它是完全图。也就是 k−1 个孤立点 + 一个 Kn−k+1,边数恰好是 (n−k+1)(n−k)/2。课件第 64 页的图是 n=7、k=4:K4 加 3 个孤立点,6 条边,(7−4)(7−4+1)/2 = 6。
证明:
- 先让每个分支变成完全图。在一个分支内部加边不会把两个分支连起来,分支数 k 不变,边数只增不减。所以只需证明"每个分支都是完全图"时结论成立。
- 设各分支点数为 n1, …, nk,n1 + ⋯ + nk = n,每个 ni ≥ 1。边数
M = [n1(n1−1) + ⋯ + nk(nk−1)] / 2
- 令 T = max ni。其余 k−1 个分支每个至少 1 个点,所以 T ≤ n − (k−1) = n−k+1。
- 每一项 ni(ni−1) ≤ T(ni−1),所以
M ≤ T[(n1−1) + ⋯ + (nk−1)] / 2 = T(n−k) / 2 ≤ (n−k+1)(n−k) / 2
∎ 课件第 65–66 页还给了另一种思路:比较两个各有 n1, n2 ≥ 2 个点的完全图分支(边数 B)和"一个 Kn1+n2−1 加一个孤立点"(边数 A),算出 A − B = (n1−1)(n2−1) > 0。意思是:把一个分支的点挪到另一个分支里,只留一个孤立点,边数会变多。反复这样做,最后就得到"k−1 个孤立点 + 一个大完全图"。
k = 1 时公式给出 n(n−1)/2,正是 Kn 的边数。反过来用:n 阶简单图如果边数 > (n−1)(n−2)/2(k=2 时的上界),它一定连通。
割集与圈
课件③ 第 69–86 页
上一节问"图连不连通",这一节问"图连得牢不牢":最少拿掉哪些点或边,图就断开了?这些关键的点和边就是网络里的薄弱环节。
引例:嗅探器(ZJOI 2004)
红军要在蓝军网络的某台中间服务器上装一个嗅探器,截获两个信息中心之间的所有数据包。数据包可以走不同的路。问:装在哪台服务器上,才能保证所有数据包都经过它?
按原题样例的边表(没有 3–4)
换成图论的说法:找一个点 v(不是 2 也不是 4),使得从 2 到 4 的每条路都经过 v。上图中 4 只连着 1,任何到达 4 的路都必须先经过 1,所以答案是 1 号服务器。下面的割点定理会告诉我们,这样的 v 正是"割点"的另一种刻画。
课件第 71 页的图里还画了一条 3–4 的连线。如果真有这条边,2 到 4 就有 2–1–4 和 2–3–4 两条不共用中间点的路,装在哪台中间服务器上都截不全。原题样例的边表里没有 3–4,答案是 1。
点割集与割点
设无向图 G = ⟨V,E⟩ 是连通图,点集 V1 ⊂ V 满足:
- G 删除 V1 的所有结点后,得到的子图不连通;
- 而删除 V1 的任意真子集后,得到的子图仍连通。
则称 V1 是 G 的一个点割集。若 {v} 是点割集,称 v 为割点。
第一条说"删掉它够用":图断开了。第二条说"一个都不多余":少删任何一个点都断不开。所以点割集是一个"极小"的断开点集。"删除一个点"指连同它关联的所有边一起删掉。
形式化写法里的 W(·) 是分支数。G 连通时 W(G) = 1,"W(G − V1) > W(G)"就是"删完不连通"。
s 是割点
展开解答
先找割点(逐个删一个点看是否断开):
- 删 v5:{v1,v2,v3,v4} 和 {v6,v7} 断开。v5 是割点。
- 删 v6:v7 被孤立。v6 是割点。
- 删其他任一点,剩下的仍连通。
再找两个点的点割集:删 v1 和 v4,v2 的两个邻居都没了,v2 被孤立。而单独删 v1 或单独删 v4 都不会断开,所以 {v1, v4} 是点割集。
还有没有别的?像 {v3, v5} 删掉后也不连通,但它的真子集 {v5} 已经能断开,违反"任意真子集删除后仍连通",所以不是点割集。我用程序枚举了所有点集,结果只有 {v1,v4}、{v5}、{v6},与课件一致。
v2、v3、v7 不在任何点割集中:比如 v7 是"叶子",删掉它只会少一个末端,别的点都还连着;把它加进任何点集里,都会让那个点集不再"极小"。
边割集与割边(桥)
设 G 是连通无向图。课件的写法是:对任意 E′ ⊆ E″ ⊆ E,图 G′ = ⟨V,E′⟩ 和 G″ = ⟨V,E″⟩ 都是 G 的子图,若 (1) G′ 是不连通图,(2) 对于任意满足 E′ ⊂ E″ 的 E″,G″ 仍是连通图,则称边集 E \ E′ 为 G 的一个割集(边割集)。
若边割集 T = {e},称 e 为 G 的割边或桥(cut edge, bridge)。
令 T = E \ E′,T 就是"要删掉的边",E′ 是"删完剩下的边"。
- (1) "G′ 不连通":删掉 T 后图断开了(删得够)。
- (2) "E″ 比 E′ 多任何边都连通":只要少删 T 中的任何一条(把它留下),图就还连通(一条都不多余)。
所以和点割集完全平行:边割集 = 删掉后图断开、而少删任意一条都不断开的边集。注意删边时点保留(G′ 的点集还是 V)。
对连通无向图 G,把 G 的结点划分成两个不相交的子集 V1、V2,使每个子集的导出子图都是连通的,则连接这两个子集的边的集合是 G 的一个割集。
为什么:设 T 是所有一端在 V1、另一端在 V2 的边。
- 删掉 T:V1 和 V2 之间没有边了,图断开(够用)。
- 少删 T 中任意一条边 e:e 把 V1 和 V2 接上,而 V1、V2 内部各自连通,所以整个图又连通了(不多余)。
"每个子集的导出子图连通"这个条件不能少。如果 V1 自己内部就是断开的两块,跨边集合里可能有多余的边:只删其中一部分图就已经断了。
展开解答
v3 是割点:删掉 v3,左边 {v1,v2} 和右边 {v4,v5} 断开。
{(v1,v3), (v2,v3)} 是边割集:用定理 10.7.1,取 V1 = {v1,v2}、V2 = {v3,v4,v5},两边的导出子图都连通,它们之间的边恰好就是这两条。同理 {(v3,v4),(v3,v5)}、{(v1,v2),(v1,v3)} 等也是边割集。
没有割边:每条边都在某个三角形上,删掉任意一条,绕三角形的另外两条边仍能走通。
这个例子说明:有割点不一定有割边。
圈与距离
圈:一条闭合链 (u1, u2, …, un, u1) 中各结点 u1, …, un 均不同,并且所有边也不同。(就是上一节的"基本回路"。)
长度:链(或圈)所含的边数,链 P 的长度记为 |P|。
距离:无向图中 u、v 之间最短链的长度,记 d(u,v)。
无向图的距离满足四条性质:不连通时 d(u,v) = ∞;d(u,u) = 0;d(u,v) = d(v,u)(对称);d(u,w) ≤ d(u,v) + d(v,w)(三角不等式:先到 v 再到 w 也是一条从 u 到 w 的链,最短链不会比它长)。
课件这里用"链"指无向图中的通路,"路"一般指不重复点的链。
割点、割边的等价刻画
⇐:u 到 w 的每条路都经过 v,那么在 G − {v} 中 u 和 w 之间一条路都没有,G − {v} 不连通,v 是割点。
⇒:v 是割点,G − {v} 至少有两个分支 G1、G2。取 u ∈ G1、w ∈ G2。G 连通,所以 G 中有 u 到 w 的路。对其中任意一条路 Γ:如果 Γ 不经过 v,它就完整地留在 G − {v} 里,u、w 就在同一个分支中,矛盾。所以 Γ 必经过 v。∎
回到嗅探器:要找的就是这样一个 v,只不过 u、w 已经指定为两个信息中心。
证明和割点完全一样,把"删点 v"换成"删边 e"。
证明:设 e = (x,y)。下面四句话一个推一个,每一步都是"当且仅当":
- e 是割边
- ⇔ 删掉 e 后,x 和 y 落在 G − {e} 的不同分支中(删掉 e 只可能把 e 的两端拆开,别的点之间原来怎么连还怎么连)
- ⇔ 在 G − {e} 中不存在 x 到 y 的路
- ⇔ e 不在任何基本回路中。因为:如果 e 在某个基本回路上,回路去掉 e 剩下的部分就是一条 x 到 y、不用 e 的路;反过来,如果有一条不用 e 的 x–y 基本路,把 e 接上就是一个包含 e 的基本回路。
∎ 一句话:桥就是不在任何圈上的边。在圈上的边删了可以绕道,桥删了没有路可绕。
Tarjan 算法:一次 DFS 找出所有割边
最直接的办法是逐条边删掉、做一次连通性检查:一共 |E| 条边,每次检查 O(|V|+|E|),总共 O(|E|(|V|+|E|))(课件写的是 O(|V|(|V|+|E|)),那是逐个点判断割点的代价)。1986 年图灵奖得主 Robert Tarjan 给出的算法只需要做一次深度优先搜索(DFS),复杂度 O(|V|+|E|)。
第一步:做一次 DFS,分出两种边
从任一点出发做 DFS。沿着它"第一次走到新点"所用的边(树枝边)构成一棵 DFS 树,其余的边叫返祖边(回边)。
理由:假设 DFS 正在处理 u,u 有一个邻居 w 还没被访问,DFS 一定会在离开 u 之前访问 w,所以 w 会成为 u 的后代。也就是说,相邻的两个点之间一定是祖先—后代关系。
这立刻告诉我们:返祖边一定不是桥(它和树上的那段路构成一个圈),只有树枝边才可能是桥。
第二步:给每个点记两个数
- dfs[u]:u 被访问的次序(时间戳),第几个被访问就是几。
- low[u]:从 u 的子树里的任意点出发,最多走一条返祖边,能到达的点的时间戳的最小值。直观地说,就是"u 这一支最高能爬回到哪"。
计算方法:先令 low[u] = dfs[u];遇到返祖边 (u, w) 时 low[u] = min(low[u], dfs[w]);子结点 v 处理完返回时 low[u] = min(low[u], low[v])。
第三步:判定
(u, v) 是割边 ⇔ (u, v) 是树枝边(u 是 v 的父结点),并且 dfs[u] < low[v]。
为什么:low[v] > dfs[u] 意思是 v 的整棵子树,靠返祖边最高也只能爬到 v 自己这一层,碰不到 u 或 u 上面的点。那么子树和外界唯一的联系就是树枝边 (u, v),删掉它子树就掉下来了,所以是桥。反之,如果 low[v] ≤ dfs[u],子树里有一条返祖边能绕到 u 或更高的地方,(u, v) 删了也能绕过去,就不是桥。
Tarjan 逐步演示(课件第 86 页的图)
每点一下执行一步。点上方的数字是 dfs/low。橙色实线是树枝边,蓝色虚线是返祖边,红色粗线是找到的桥。DFS 时邻居按编号从小到大访问,得到的 DFS 树和课件完全一致。
最后的结果与课件第 86 页的表一致:dfs = (1,2,3,4,5,6,7,9,8),low = (1,1,1,1,2,6,7,1,1)(按结点 1~9 排列)。检查每条树枝边:
- (5, 6):dfs[5] = 5 < low[6] = 6,是桥。
- (6, 7):dfs[6] = 6 < low[7] = 7,是桥。
- (4, 5):low[5] = 2(5 有返祖边连到 2),dfs[4] = 4 ≮ 2,不是桥。
- (4, 9):low[9] = 1(经 8 的返祖边到 1),不是桥。其余同理。
同样的 dfs/low 也能找割点:非根结点 u 是割点 ⇔ 它有某个子结点 v 满足 dfs[u] ≤ low[v](注意是 ≤);根结点是割点 ⇔ 它在 DFS 树上有至少两个子结点。这张图里割点是 5 和 6。
支配集、覆盖集与独立集
课件③ 第 88–100 页
这一节的概念都是同一个模式:从图里选一些点或边,要求它们满足某种"照顾到"或"互不冲突"的条件,然后问最少(或最多)要选几个。下面先给全景,再逐个讲。
| 名称 | 选什么 | 条件 | 求 |
|---|---|---|---|
| 支配集(10.8.1) | 点 | 没选中的每个点,都和某个选中的点相邻 | 最少 |
| 覆盖集(10.8.4,课件用法) | 边 | 每个点都是某条选中边的端点("边覆盖点") | 最少 |
| 独立集(10.8.7,课件用法) | 边 | 选中的边两两不相邻(不共用端点),即匹配 | 最多 |
| 点覆盖(第 99–100 页) | 点 | 每条边至少有一个端点被选中("点覆盖边") | 最少 |
本课件的"覆盖集"和"独立集"是边的集合。很多教材里"独立集"指两两不相邻的点集,"覆盖"指点覆盖。课件最后讲的"最小覆盖集问题"又换成了点覆盖。做题时先看清题目定义的是点还是边。
极小:满足条件,并且去掉任何一个元素就不满足了(不能再减)。
最小:在所有满足条件的集合里,元素个数最少。
最小的一定是极小的(如果还能去掉一个,它就不是最少),但极小的不一定是最小的。极大 / 最大同理(不能再加 / 个数最多)。
下面所有例子都用课件里这张 8 个点、11 条边的图(v7、v8 分别在两条对角线的中间):
支配集
引例(选址问题,课件第 93 页):要在 n 个地点中选若干处设应急中心,使每个地点要么本身是应急中心,要么和至少一个应急中心直接相邻。为了省钱,中心要尽量少。应设几个?设在哪?
设无向图 G = ⟨V,E⟩,V* ⊆ V。若对任意 u ∈ V − V*,V* 中都有 v 使得 (u,v) ∈ E,则称 v 支配 u,并称 V* 是支配集。
极小支配集:V* 是支配集,并且它的任意真子集都不是支配集。
最小支配集:点数最少的支配集,即 min{|V*|}。
对照课件的图:
- {v2, v3, v4, v6} 是支配集(课件第 95 页):v1 被 v2 支配,v5 被 v4 或 v6 支配,v7 被 v2 支配,v8 被 v3 支配。但它不是极小的:去掉 v4,v4 自己被 v3 支配,其余点照旧被支配,剩下的 {v2, v3, v6} 仍是支配集。
- {v2, v5} 是最小支配集(课件第 96 页右图):v2 支配 v1、v3、v7,v5 支配 v4、v6、v8。
- 为什么不可能只用 1 个点:度最大的点 v2、v5 度都是 4,一个点最多照顾到自己和 4 个邻居共 5 个点,不够 8 个。所以最小支配集大小是 2。程序枚举可知只有 {v2, v5} 和 {v3, v6} 两个。
- {v1, v2, v3} 是极小支配集但不是最小的:去掉 v1,v6 就没人支配;去掉 v2,v7 没人支配;去掉 v3,v4 没人支配。它不能再减,可是比 {v2, v5} 多一个点。
所以选址问题的答案是:至少设 2 个应急中心,可以设在 v2、v5,或 v3、v6。
设无向图 G 中无孤立结点,V1* 为 G 的一个极小支配集,则 G 存在另一个极小支配集 V2*,使得 V1* ∩ V2* = ∅。
课件只给了结论。证明分两步,核心是证明"剩下的点 V − V1* 本身也是支配集"。记 D = V1*。
- D 中每个点 v 都有邻居在 D 外面。 D 是极小的,去掉 v 后 D − {v} 不再是支配集,所以有某个点 w 没被 D − {v} 支配。分两种情况:
- w 就是 v 自己:说明 v 在 D 里没有邻居。可是 G 没有孤立点,v 总有邻居,那这个邻居只能在 D 外面。
- w 是 D 外面的点:w 原来被 D 支配,去掉 v 后就不被支配了,说明 w 唯一的 D 中邻居是 v。于是 w 就是 v 在 D 外面的邻居。
- 所以 V − D 是支配集:不在 V − D 中的点就是 D 中的点,由第 1 步它们都和 V − D 中的某点相邻。
- V − D 是支配集,但不一定极小。从中不断去掉多余的点,直到不能再去,得到一个极小支配集 V2* ⊆ V − D,它和 D 不相交。∎
例:{v2, v5} 是极小支配集,V − {v2,v5} = {v1,v3,v4,v6,v7,v8} 是支配集,从中可以减出 {v3, v6}。"无孤立点"不能去掉:孤立点必须属于每一个支配集(没人能支配它),两个支配集就不可能不相交。
覆盖集(课件定义:边覆盖点)
设无向图 G = ⟨V,E⟩,E* ⊆ E。若对任意 u ∈ V 都有 e ∈ E* 使得 u | e(u 是 e 的端点),则称 e 覆盖 u,E* 是覆盖集。
E* 的任何真子集都不是覆盖集,则 E* 是极小覆盖集。
边数最少的覆盖集是最小覆盖集,即 min{|E*|}。
说人话:挑一些边,让每个点都至少被一条挑中的边碰到。显然有孤立点的图不存在覆盖集。
(课件第 100 页左图)
(课件第 100 页右图)
左图为什么是极小的:每条边都"独占"某个点,例如 (v1,v2) 是唯一碰到 v1 的边,(v2,v3) 是唯一碰到 v3 的边,去掉任何一条都有点没被覆盖。右图为什么是最小:一条边最多覆盖 2 个点,8 个点至少要 4 条边,右图正好 4 条,而且这 4 条边两两不共用端点。
独立集(课件定义:两两不相邻的边,即匹配)
设无向图 G = ⟨V,E⟩,E* ⊆ E。若 E* 中任意两条边都不相邻,则称 E* 是独立集。
若对任意满足 E1* ⊂ E2* 的 E2*,E2* 都不是独立集,则 E1* 是极大独立集(再加任何一条边都会冲突)。
边数最多的独立集是最大独立集,即 max{|E*|}。
两条边"相邻"就是共用一个端点(10.2 节的定义)。所以独立集就是一组互不共用端点的边,在别的教材和算法课里叫匹配(matching):可以想成给点两两配对,每个点最多配一次。
(课件第 102 页、第 103 页左图)
(课件第 103 页右图)
课件第 103 页把左图放在"极大独立集"的定义旁边,但它只有 (v1,v2)、(v4,v5) 两条边,还可以再加入 (v6,v7) 和 (v3,v8) 而不冲突,所以严格按定义它不是极大的。加满之后就是右图。
上面两张"最小覆盖集"和"最大独立集"的右图用的是同一组 4 条边,这不是巧合。对没有孤立点的 n 阶图,有 Gallai 定理:最小覆盖集的边数 + 最大独立集的边数 = n。这里 4 + 4 = 8。
直观理解:先拿一个最大匹配(k 条边,覆盖 2k 个点),剩下 n − 2k 个点每个再补一条边,总共 k + (n−2k) = n − k 条边就覆盖了所有点。
最小点覆盖问题
这里选的是点,要求每条边都被碰到,和上面的"覆盖集"方向正好相反。应用:软件测试里,"点覆盖"指测试用例要经过程序控制流图的所有结点,"边覆盖"指要经过所有边(课件第 99 页)。这个问题是 NP 难的,没有已知的多项式时间精确算法。
2-近似算法
- 令 E′ = ∅,A = ∅。
- 只要还有边没处理:任取一条边 (u, v),放进 E′,把 u 和 v 都加入 A,然后删掉所有和 u 或 v 相邻的边(它们已经被覆盖了)。
- 没边了就停止,输出 A。
A 是点覆盖:每条边要么被选进了 E′(两端都在 A 中),要么是因为和某条选中的边相邻而被删掉(共用的那个端点在 A 中)。
近似比 ≤ 2(为什么最多只比最优多一倍):
- E′ 中的边两两不相邻(选一条就删掉它所有相邻边),也就是说 E′ 是一个独立集(匹配)。
- 设 OPT 是最优解。OPT 要覆盖 E′ 的每条边,每条边至少要用一个端点。E′ 的边互不共用端点,所以 OPT 至少要用 |E′| 个不同的点:|E′| ≤ |OPT|。
- A 恰好由 E′ 的端点组成:|A| = 2|E′| ≤ 2|OPT|,即 |A| / |OPT| ≤ 2。
在下面实验的"点覆盖"模式里可以运行这个算法,看看它在课件这张图上给出几个点。
POJ 3041 Asteroids:二部图上的点覆盖
题目:N×N 网格里有 K 颗小行星,第 i 颗在 (Ri, Ci)。一发光束能清除一整行或一整列。最少几发?课件的例子:小行星在 (1,1)、(1,3)、(2,2)、(3,2)。
建模:上面一排点代表"行",下面一排点代表"列",每颗小行星 (r, c) 连一条边 r–c。打一发行光束 = 选中一个行点,它清除这一行所有小行星 = 覆盖这个点关联的所有边。所以"清除所有小行星的最少发数" = 这个二部图的最小点覆盖。
一般图的点覆盖是 NP 难的,但二部图有 König 定理:最小点覆盖的点数 = 最大匹配的边数,而最大匹配可以用匈牙利算法在多项式时间内求出。这里最大匹配是 {行1–列1, 行2–列2},2 条,所以答案是 2。下界的理由和近似算法一样:匹配中的边互不共用端点,每条都需要一个不同的点去覆盖。
支配集 / 覆盖 / 独立集实验
先选模式,然后点击顶点(支配集、点覆盖)或边(覆盖集、独立集)进行选择。右边实时判断是否满足条件、是否极小(极大)、和最优值差多少。
第十一章 · 欧拉图
课件④ 第 1–32 页
第十一章叫"图的基本问题",本章内容分三块:穿程问题(欧拉图、哈密顿图、骑士周游)、通路问题(最短通路、关键通路)、匹配问题(二分图)。这份课件讲的是前两个:欧拉图和哈密顿图。
对图 G,从一个指定结点出发,恰好经过每条边一次并回到该点,怎么走?(欧拉问题)
从一个指定结点出发,恰好经过每个结点一次并回到该点,怎么走?(哈密顿问题)
这类"遍历每条边"或"遍历每个结点"的问题统称穿程问题。
| 欧拉(Euler) | 哈密顿(Hamilton) | |
|---|---|---|
| 要求 | 每条边恰好一次,点可以重复 | 每个点恰好一次,边不必全走 |
| 判断 | 看度数的奇偶,简单的充要条件 | 没有简单的充要条件,只有充分条件和必要条件 |
| 复杂度 | 多项式时间,O(|V|+|E|) 就能判断 | NP 完全,一般只能搜索 |
哥尼斯堡七桥问题与一笔画
普雷格尔河把城市分成 4 块陆地:两岸 C、D 和两个岛 A、B,之间有 7 座桥。问:能否从某块陆地出发,每座桥恰好走一次,最后回到出发点?
度数:A = 5,B = 3,C = 3,D = 3
课件第 7 页把边写成三元组 (A, C, 1), (A, C, 2),第三个分量是给两座平行的桥编号,这样它们就是两条不同的边。
欧拉在 1736 年证明了这是不可能的,而且不能走成"不回到起点"的版本(课件第 8 页:"既无欧拉回路,又无欧拉路径")。理由在下面的定理里:4 个点的度都是奇数。
一张连通图能由一笔画出来(每条线恰好画一次、笔不离纸),当且仅当:
- 每个交点处的线条数都是偶数(这时能画成回到起点的欧拉回路);或
- 恰有两个交点处的线条数是奇数(这时能画成欧拉链,从一个奇点画到另一个奇点)。
"交点处的线条数"就是这个点的度。所以一笔画问题完全由度数的奇偶决定,下面是严格的定义和定理。
定义
设 G = ⟨V,E⟩ 是连通无向图,经过 G 中每条边一次且仅一次的简单回路称为欧拉圈,也称欧拉回路。具有欧拉圈的图称为欧拉图。
经过 G 中每条边一次且仅一次的简单通路称为欧拉链(欧拉通路),起点和终点可以不同。
课件里那两行逻辑式正好对应"恰好一次"的两半:第一行说每条边都出现(至少一次),第二行说出现的边互不相同(至多一次)。
例:判断四个图(课件第 11–14 页)
欧拉圈 abcda
欧拉圈 abecdea
欧拉链 abcdaceb,无欧拉圈
既无欧拉圈也无欧拉链
观察出的规律:有欧拉圈的图所有结点度数都是偶数;只有欧拉链的图恰有两个奇点,欧拉链就从一个奇点走到另一个;奇点有 4 个的 G4 两样都没有。下面把这个规律证明出来。
欧拉图的判定定理
设 G 是连通无向图,下面三个命题等价:
- G 是欧拉图;
- G 中所有结点的度数都是偶数;
- G 是若干个边不重的圈的并(定理 11.2.3)。
证明分三步:先证 1 ⇒ 2(定理 11.2.2,必要性),再证 2 ⇒ 1(定理 11.2.1,充分性),最后 2 ⇔ 3 在证明 2 ⇒ 1 的过程中顺带得到。
必要性:欧拉图 ⇒ 连通且每点度为偶数(定理 11.2.2)
连通:欧拉圈经过所有边,任意两个有边的点都在这条回路上,沿回路就能互相到达。(定义里本来就要求了 G 连通。)
度为偶数:沿欧拉圈走一圈。每次"路过"一个点,都是从一条边进来、从另一条边出去,给这个点的度贡献 2。起点也一样:出发时用掉一条边,最后回来时又用掉一条,合起来也是 2。每条边恰好被走一次,所以每个点的度 = 2 × 它被路过的次数,是偶数。
充分性:连通且每点度为偶数 ⇒ 欧拉图(定理 11.2.1)
证明要用到一个辅助事实:每点度数都是偶数(且有边)的图里一定有圈。理由就是 10.6 节非循环图那条定理:所有点度 ≥ 2 的图不是非循环图。直观地说:从任一点出发沿没走过的边走,每进入一个点,因为度是偶数,进来用掉一条边后还剩奇数条,至少有一条可以出去,所以不会被卡住,点数有限,最后一定走回走过的点,形成一个圈。课件定义 11.2.3 的"极大路径"(不能再延长的路径)就是用来严格写这个论证的:极大路径的端点的所有邻居都在路径上,而它度 ≥ 2,所以它还连着路径上另一个点,这就构成圈。
证明(对边数 m 归纳,课件第 16–18 页):
- 起步:G 是平凡图(没有边)时结论成立。m = 1 时,连通且度为偶数,唯一的边只能是一个自环,自环本身就是欧拉圈。
- 归纳假设:设边数 ≤ k 时结论都成立,看 m = k+1。
- 取一个圈 C:由上面的辅助事实,G 中有圈 C。把 C 上所有的边删掉,得到生成子图 G′。
- G′ 的每个分支都满足归纳假设:C 经过每个点时用掉这个点的 2 条边(或 0 条),所以删掉 C 后每个点的度仍是偶数。G′ 可能不连通,设它有若干个分支 G′1, …, G′n,每个分支连通、度数全偶、边数 ≤ k,由归纳假设,每个 G′i 都是欧拉图,有自己的欧拉回路。
- 每个分支都和 C 有公共结点:G 是连通的,G′i 原来和外面相连只能靠 C 的边,所以 G′i 一定碰到 C,设公共结点为 vij。
- 拼接:沿着 C 走,每走到一个 vij,就先把 G′i 的欧拉回路从 vij 出发走一遍再回到 vij,然后继续沿 C 往前走。走回起点时,C 的边和所有 G′i 的边都恰好走了一次,这就是 G 的欧拉回路。∎
从这个证明还能看出:不断"拿出一个圈",最后边全部拿完,所以欧拉图是若干个边不相交的圈的并(命题 3)。反过来,若干个边不重的圈并起来,每个圈给经过的点贡献 2 度,所以每点度为偶数,连通时就是欧拉图。
例:把证明过程走一遍(课件第 19 页)
欧拉回路 u4u7u5u6u4
欧拉回路 u3u1u2u3
拼接:沿 C 从 u4 出发。在 u4 先插入分支 1 的回路 u4u7u5u6u4,然后沿 C 走到 u3,在 u3 插入分支 2 的回路 u3u1u2u3,再沿 C 经 u5 回到 u4:
10 条边全部恰好走一次。注意 u4、u5、u3 都经过了两次,这在欧拉回路里是允许的。
欧拉链的判定(定理 11.2.4)
无向图 G 中有连接 ui 和 uj(ui ≠ uj)的欧拉链,当且仅当 G 是连通图,并且 G 中只有 ui 和 uj 是奇结点。
证明思路:加一条边,把欧拉链变成欧拉回路(课件第 23–26 页)。令 e 是一条连接 v1、v2 的新边(如果 G 里已经有边 (v1,v2),就加一条与它平行的新边),G′ = G + {e}。下面每一步都是"当且仅当":
- G 有一条从 v1 到 v2 的欧拉链
- ⇔ G′ 有一条欧拉回路(欧拉链走到 v2 后再沿 e 回到 v1,就是 G′ 的欧拉回路;反过来,G′ 的欧拉回路去掉 e 就是 G 中 v1 到 v2 的欧拉链)
- ⇔ G′ 是欧拉图
- ⇔ G′ 中每个结点都是偶结点(上面的判定定理)
- ⇔ G 中恰有两个奇结点 v1 和 v2(加边 e 只让 v1、v2 的度各加 1,别的点不变)。∎
课件第 25–26 页讨论了 e ∈ E 的情形(v1、v2 本来就相邻),把 G − {e} 拆成两个圈来处理。用"加一条平行边"的写法可以把两种情形统一起来,因为欧拉图的判定定理对有平行边的图同样成立(七桥图本身就有平行边)。
先确认图连通(孤立点不影响,忽略它),再数奇数度的点有几个:
- 0 个:有欧拉回路,从任何点出发都行;
- 2 个:没有欧拉回路,但有欧拉链,必须从一个奇点出发、到另一个奇点结束;
- 4 个、6 个……:两样都没有。(奇点个数一定是偶数,这是握手定理的推论,所以不会出现 1 个或 3 个。)
序列图是欧拉图(课件第 21 页)
10.3 节的 0-1 序列图 Sm(m = 3 时 8 个点)每个点入度 2、出度 2,课件的 degreeset 函数算出度数全是 4,所以按无向图看它是欧拉图(自环 (0,0)、(7,7) 算 2 度)。对有向图也有同样的定理:弱连通有向图有有向欧拉回路 ⇔ 每个点入度 = 出度(课件第 21 页那两个公式就是入度、出度的定义)。
拓展:Sm 的有向欧拉回路有一个漂亮的用途。每条边对应一个 m+1 位 0-1 串,沿欧拉回路依次写下每条边的最后一位,就得到一个长 2m+1 的环形 0-1 序列,每个 m+1 位串恰好在其中出现一次(De Bruijn 序列)。这正是"序列图"这个名字的来源。
Fleury 算法:实际把欧拉回路找出来
判定定理只告诉我们"有没有",Fleury 算法告诉我们"怎么走"。
输入:无向图 G。输出:从 v 到 w 的欧拉链或欧拉圈。
- 从任意一点开始(有两个奇点时必须从奇点开始),沿着没走过的边向前走;
- 在每个顶点,优先选择剩下的非桥边,除非只剩唯一一条边可走;
- 直到得到欧拉回路,或宣布失败。
"桥"是相对于剩下还没走的边而言的:把已经走过的边擦掉,在剩下的图里,如果某条边一删掉就会把图分成两块,它就是桥。
为什么不能随便走桥:桥是两块之间唯一的通道。如果另一侧还有没走的边,过了桥就回不来,留在这一侧的边就再也走不到了。所以只有在"别无选择"时才过桥,这时过桥后另一侧就是剩下的全部。
课件第 28 页的动画演示的就是在下面这张图上用 Fleury 算法从左上角出发走一圈。在下面的实验里可以一步步看到每一步为什么这样选,也可以自己点边走,故意走桥看看会怎么卡住。
欧拉回路 / Fleury 实验
选一张图,先看度数判断,再走。"Fleury 走一步"会按算法自动选边并说明理由;你也可以直接点击与当前点(橙色)相连的边自己走。走过的边标了序号。
展开解答
先算度数:A = 4,B = 3,C = 4,D = 4,E = 3(B 和 E 之间没有边)。只有 B、E 是奇点。
由定理 11.2.4,图中有从 B 到 E 的欧拉链,例如 B → A → C → B → D → A → E → C → D → E(9 条边各一次)。乙从 B 出发沿这条链走,恰好爬 9 条边就到 E。
甲从 A 出发。A 是偶点,以 A 为起点、每条边恰好一次的走法要么是欧拉回路(终点回到 A),要么是欧拉链(但欧拉链的起点必须是奇点)。所以甲不可能只爬 9 条边就"爬遍且停在 E",至少要重复爬某条边,路程比 9 条边长。
答:乙先到达 E。(可以在上面的实验里选"蚂蚁例题",分别从 A 和 B 出发试试。)
中国邮递员问题
1962 年,中国数学家管梅谷提出并解决了这个问题,所以国际上叫它 Chinese Postman Problem。
和欧拉问题的区别:欧拉要求每条边恰好一次,这里允许重复,只求总长最短。
- 街道图本身是欧拉图:直接用 Fleury 算法走一条欧拉回路,每条街恰好一次,这显然最短。
- 不是欧拉图:必须重复走一些街道。重复走一条边,相当于在图里给它再添一条平行边。目标变成:添一些边,使所有点的度都变成偶数(图变成欧拉图),并且添的边总权值最小。
若 W 是包含图 G 的每条边至少一次的回路,则 W 的总权值最小,当且仅当:
- G 的每条边在 W 中最多重复一次;
- 对于 G 的每个圈,圈上在 W 中重复的边的总权值不超过该圈上不重复的边的总权值(即不超过圈长的一半)。
两个条件为什么合理:
- (1) 如果某条边重复了 2 次以上(一共走了 3 次或更多),去掉其中两次,每个端点的度都减 2,奇偶不变,仍然能走成回路,路程却更短。所以最优解里每条边最多多走一次。
- (2) 在某个圈上,如果重复边的总长超过了圈长的一半,就把这个圈上"重复"和"不重复"对调:原来重复的改成不重复,原来不重复的改成重复。圈上每个点的度变化 0 或 ±2,奇偶不变,仍可走成回路,而重复的总长变成了原来不重复的那部分,更短。所以最优解一定满足 (2)。
课件最后提到 Edmonds–Johnson 算法可以在 O(n3) 时间内求出最优解。它的核心是:把所有奇点两两配对,每一对之间沿最短路添一遍重复边,选总长最小的配对方式。
展开解答
第 1 步:数奇点。邮局(连老年公寓、区政府、学校)度 3,老年公寓度 1,区政府(邮局、卫生院、X)度 3,X(区政府、卫生院、学校)度 3,卫生院、学校度 2。奇点有 4 个:邮局、老年公寓、区政府、X。不是欧拉图,必须重复走一些街道。
第 2 步:奇点两两配对,比较三种配法。4 个奇点配成 2 对,只有 3 种配法。每对之间按最短路添重复边:
| 配对 | 两对的最短路 | 重复总长 |
|---|---|---|
| {邮局, 老年公寓} + {区政府, X} | 1000 + 800 | 1800 |
| {邮局, 区政府} + {老年公寓, X} | 900 + (1000 + 1700) | 3600 |
| {邮局, X} + {老年公寓, 区政府} | 1700 + (1000 + 900) | 3600 |
(邮局到 X 的最短路是 邮局–区政府–X = 1700,比 邮局–学校–X = 1800 短。)
第 3 步:最优是重复走"邮局–老年公寓"和"区政府–X"两条街。所有街道总长 1000+900+600+850+800+1000+1200 = 6350 米,加上重复的 1800 米,最短路程 8150 米。
添边后每个点度数都是偶数,可以走出一条回路,例如:邮局 → 老年公寓 → 邮局 → 区政府 → X → 区政府 → 卫生院 → X → 学校 → 邮局。
检查管梅谷的两个条件:每条边最多重复一次 ✓;圈 邮局–区政府–X–学校–邮局 长 3500,其中重复边 区政府–X 长 800 ≤ 1750 ✓;圈 区政府–卫生院–X–区政府 长 2650,重复 800 ≤ 1325 ✓;其余的圈同理。老年公寓那条街是桥,不在任何圈上,必须走两次(去和回)。
第十一章 · 哈密顿图
课件④ 第 33–60 页
哈密顿问题是爱尔兰数学家哈密顿在 1857 年发明的智力题("周游世界"游戏):正十二面体的 20 个顶点代表 20 个城市,从一个城市出发,每个城市恰好经过一次,最后回到出发城市。也就是判断图中是否存在一条遍历所有结点的简单回路。
哈密顿通路:无向图 G 中穿过每个结点一次且仅一次的非闭合通路(也叫哈密顿链、哈密顿路)。
哈密顿圈:穿过每个结点一次且仅一次的圈(也叫哈密顿回路)。具有哈密顿圈的图称为哈密顿图。
哈密顿要求的是每个点恰好一次(起点终点重合的那一次除外),对边没有要求:不需要走遍所有边。欧拉要求每条边恰好一次,点可以重复。
两者互不蕴含。例如彼德森图(下面会看到)不是哈密顿图,也不是欧拉图(每点度为 3,奇数);领结图(两个三角形共用一点)是欧拉图,但不是哈密顿图(中间那个点必须经过两次);K4 是哈密顿图,但每点度 3,不是欧拉图。
20 个点,30 条边,每点度 3
为什么难(课件第 35–36 页):通常没有简单的判断方法。最直接的做法是把 20 个城市排成一个顺序,检查相邻两个是否有边。排列一共 20! = 2432902008176640000 种,即使每秒验证 10000 种,也要约 771 万年,复杂度 O(n!)。哈密顿圈问题是 NP 完全问题,至今没有已知的多项式时间算法。
回溯搜索:课件的周游算法
比起盲目枚举所有排列,更聪明的做法是沿着边一步步延长路径,走不下去就退回一步换个方向(回溯)。走不通的分支会被提前剪掉,不用把整个排列写完再检查。
第一步:建邻接表(课件第 39–40 页)
对每个结点 u,列出和它相邻的所有结点,记为 [u, [v | (u,v) ∈ E]]。课件的 adjacentlist(V,E) 对每个点 w 扫一遍边集,把另一端加进列表并排序。例如十二面体图中:
['a', ['b', 'n', 't']] ['b', ['a', 'c', 'l']] ['c', ['b', 'd', 's']] ...
有了邻接表,"从 w 能走到哪些点"就能直接查到,不用每次扫全部边。
第二步:三个函数(课件第 41–46 页)
| 函数 | 做什么 |
|---|---|
tourpath0(前进) | 取路径末尾结点 w,按邻接表顺序找第一个不在路径上的邻居 u,加到路径末尾;重复,直到路径长度达到 m(= 点数)或者末尾结点没有新邻居可走 |
tourpath1(回溯) | 弹出末尾结点 v,回到它前一个结点 u,在 u 的邻接表里从 v 之后继续找下一个不在路径上的邻居;找到就加上并结束,找不到就继续往回弹 |
tourpath | 若已经是一条完整的哈密顿通路(长度 = m),先回溯一步以便找下一条;否则交替执行前进和回溯,直到得到新的哈密顿通路或路径被弹空 |
Hamiltonpath(V,E,v0) | 建邻接表,从起点 v0 出发反复调用 tourpath,把找到的每一条哈密顿通路存进集合 paths |
"从 v 之后继续找"是关键:回溯回到 u 时,排在 v 前面的邻居已经试过了,不用再试,这保证了不重复、不遗漏。
运行结果(课件第 47–51 页)
- 十二面体图从 a 出发,共找到 162 条哈密顿通路。其中终点是 a 的邻居(b、n、t)的,再加一条边就能回到 a,构成哈密顿圈。课件第 47 页的代码
if path[-1] in ['b','n','t']就是在筛选这些,我用程序验证共有 60 条。所以十二面体图是哈密顿图,"周游世界"有解。 - 彼德森图从每个结点出发都有 24 条哈密顿通路,10 个点共 240 条,但没有一条能闭合:彼德森图没有哈密顿圈,不是哈密顿图。它每点度都是 3,也不是欧拉图。
回溯搜索实验
按课件的算法(邻接表按字母排序)一步步搜索哈密顿通路。橙色是当前路径,蓝色虚线表示找到的通路能闭合成哈密顿圈。彼德森图回溯最明显。
哈密顿图的充分条件
既然没有简单的充要条件,就退而求其次:给出"只要满足就一定是哈密顿图"的条件。共同的直觉是:边越多、每个点的度越大,越容易找到哈密顿圈。
对于 n ≥ 3 的简单图 G,如果 G 的最小度
那么 G 是哈密顿图。(δ(G) 是 G 的顶点度数的最小值。)
证明(反证法 + "极大"反例):
- 构造一个"极大"的反例。假设定理不成立,有满足条件的非哈密顿图。往里面不断加边,只要加完仍不是哈密顿图就继续加。加边不会让度变小,条件 δ ≥ n/2 一直满足;而 Kn(n ≥ 3)是哈密顿图,所以加边过程一定在某处停下。停下时得到的 G 满足:G 不是哈密顿图,但再加任何一条边都会变成哈密顿图。这就是课件说的"极大非哈密顿简单图"。显然 G 不是完全图。
- 得到一条哈密顿路。取两个不相邻的顶点 u、v。由极大性,G + uv 是哈密顿图,而且它的每个哈密顿圈都必须用到新边 uv(否则这个圈在 G 里就存在了)。把这个圈里的 uv 去掉,得到 G 中一条从 u 到 v 的哈密顿路:
P = v1v2 ⋯ vn, v1 = u,vn = v
- 定义两个下标集合。
S = { vi | uvi+1 ∈ E(G) }, T = { vi | viv ∈ E(G) }S 是"u 的每个邻居在路上的前一个点"组成的集合,T 是 v 的邻居集合。u 的每个邻居 vi+1 对应 S 中唯一的 vi,所以 |S| = d(u);|T| = d(v)。
- |S ∪ T| < n。S 中的点下标 i ≤ n−1(因为 vi+1 要存在),所以 vn ∉ S;v 不和自己相邻,所以 vn ∉ T。S ∪ T 最多包含 v1, …, vn−1,|S ∪ T| ≤ n−1 < n。
- S ∩ T = ∅。否则设 vi ∈ S ∩ T,即 uvi+1 ∈ E 且 vivn ∈ E。那么
v1 → vi+1 → vi+2 → ⋯ → vn → vi → vi−1 → ⋯ → v1是 G 中经过所有点的圈(下图),G 是哈密顿图,与假设矛盾。(课件第 55 页写成 "|S ∩ T| = ∅",应为 S ∩ T = ∅,即 |S ∩ T| = 0。)
- 导出矛盾。
d(u) + d(v) = |S| + |T| = |S ∪ T| + |S ∩ T| < n + 0 = n但 δ(G) ≥ n/2 意味着 d(u) + d(v) ≥ n/2 + n/2 = n,矛盾!∎
回头看,第 6 步只用到了"不相邻的 u、v 满足 d(u) + d(v) ≥ n"。所以同一个证明其实证明了更强的 Ore 定理:n ≥ 3 的简单图中,若任意两个不相邻的结点度数之和 ≥ n,则 G 是哈密顿图。Dirac 定理是它的特例。课件第 57 页的第二条("每一对节点的次数之和大于等于 n,则存在哈密顿圈")就是这个结论。
定理 11.2.5:哈密顿链的充分条件
设 G 是具有 n(n ≥ 3)个结点的无向简单图。若 G 中每一对结点的度数之和 ≥ n − 1,则 G 中存在一条哈密顿链。
条件比 Dirac 弱了 1(n−1 而不是 n),结论也弱一些:只保证哈密顿链,不保证闭合成圈。证明分三步。
1. G 是连通的(反证法)。若不连通,至少有两个分支 G1、G2,各取一点 u ∈ G1、v ∈ G2。u 的邻居只能在 G1 里,d(u) ≤ |G1| − 1,同理 d(v) ≤ |G2| − 1。于是 d(u) + d(v) ≤ |G1| + |G2| − 2 ≤ n − 2,与条件矛盾。(这和 10.6 节"连通的充分条件"是同一个结论。)
2. 取最长的基本路径,证明它能闭合成圈。设 Γ = v1v2 ⋯ vl 是 G 中最长的基本路径(点不重复)。如果 l = n,它就是哈密顿链,证毕。下面设 l < n,证明存在一个经过 v1, …, vl 全部 l 个点的圈。
- (i) v1 与 vl 相邻:Γ 加上边 (v1, vl) 就是这样的圈。
- (ii) v1 与 vl 不相邻:
- Γ 是最长的,所以 v1、vl 只能和 Γ 上的点相邻(如果 v1 有一个 Γ 外的邻居 w,把 w 接在前面就得到更长的基本路径)。
- 设 v1 与 vi1, vi2, …, vik 相邻,共 k = d(v1) 个点。
- vl 不能和任何 vij−1 相邻,否则下面就是经过 Γ 全部点的圈(和上面 Dirac 证明里的交叉弧完全一样),已经找到了:v1 → vij → ⋯ → vl → vij−1 → ⋯ → v1
- 所以如果圈不存在,vl 的邻居只能在 v1, …, vl−1(l − 1 个点)中,并且要去掉这 k 个"禁区"点,最多 l − 1 − k 个。
- 于是 d(v1) + d(vl) ≤ k + (l − 1 − k) = l − 1 < n − 1,与条件矛盾。所以圈一定存在。
3. 扩展路径,导出矛盾。现在有一个经过 Γ 上全部 l 个点的圈 C,而 l < n,所以 Γ 外还有点。G 连通,所以一定有 Γ 外的点 v 与 C 上某点 vj 相邻(一个圈 + 一个点)。从 v 出发走到 vj,再沿 C 绕一圈(不闭合),得到一条有 l + 1 个点的基本路径,比 Γ 还长,与"Γ 最长"矛盾。所以 l = n,Γ = v1v2 ⋯ vn 是哈密顿链。∎
课件第 57 页还列了两条相关结论:每一对结点度数之和 ≥ n 时存在哈密顿圈(上面的 Ore 定理);有向完全图(竞赛图)中必存在哈密顿通路(勒代定理,见 10.6 节)。课件特别强调:这些定理都是充分条件。
有一个简单的必要条件:若 G 是哈密顿图,则对 V 的任意非空子集 S,删去 S 后的分支数 W(G − S) ≤ |S|。理由:哈密顿圈 C 删去 |S| 个点,最多断成 |S| 段,而 G − S 包含 C − S 的所有点和边,分支只会更少。
用法是找一个反例 S:例如领结图,删去中间 1 个点得到 2 个分支,2 > 1,所以不是哈密顿图;K2,3 删去左边 2 个点,剩下 3 个孤立点,3 > 2,也不是。注意它同样只能用来否定。彼德森图满足这个条件,却不是哈密顿图,只能靠更细的论证或者像课件那样用程序穷举。
自测
点选项即判对错并显示解析。每题只能选一次,刷新页面可重来。
公式与易错点速查
公式
| 内容 | 结论 |
|---|---|
| 握手定理 | ∑d(v) = 2m;有向 ∑di = ∑do = m;奇度点个数为偶数 |
| Kn | n 点,n(n−1)/2 边,(n−1) 正则 |
| Cn | n 点,n 边,2 正则 |
| Wn(课件记法) | n 点,2(n−1) 边;圈上点度 3,中心度 n−1 |
| Km,n | m+n 点,mn 边 |
| Qn | 2n 点,n·2n−1 边,n 正则,二部图 |
| Sm(0-1 序列图) | 2m 点,2m+1 条有向边,入度 = 出度 = 2 |
| 彼德森图 | 10 点,15 边,3 正则 |
| r 正则图存在 | r ≤ n−1 且 nr 为偶数 |
| 补图 | |E| + |E(~G)| = n(n−1)/2,d(v) + d~G(v) = n−1 |
| 自补图 | n ≡ 0, 1 (mod 4),边数 n(n−1)/4 |
| 无三角形图 | 边数 ≤ ⌊n²/4⌋,K⌊n/2⌋,⌈n/2⌉ 取等 |
| Ak | (Ak)ij = i 到 j 长度为 k 的通路数;简单图 (A²)ii = d(vi) |
| 可达矩阵 | R = B(I + A + ⋯ + An−1) = B[(I+A)n−1] |
| 距离矩阵 | dij = 使 akij > 0 的最小 k(0 ≤ k < n),没有则 ∞ |
| 二部图 | ⇔ 无奇数长回路 ⇔ 奇数 k 时 Ak 对角线全 0 |
| 通路长度 | 可达 ⇒ 存在长度 ≤ n−1 的基本通路 |
| 有向连通 | 强连通 ⇔ 有完备回路;单向连通 ⇔ 有完备通路;强 ⇒ 单向 ⇒ 弱 |
| 竞赛图 | 勒代定理:一定有有向哈密顿通路 |
| 分支 | 极大连通子图;连通 ⇔ 恰 1 个分支;强分支把结点分干净,单向分支可重叠 |
| 连通 ⇔ 划分 | G 连通 ⇔ V 的任意划分 {V₁,V₂} 都有跨边 |
| 回路(图) | 连通 2 度正则图;⇔ |V| = |E| 且能从 v 一笔走完所有点和边回到 v |
| 有向回路判定 | 有子图每点出度(或入度)> 0 ⇒ 有有向回路;W-过程删出度或入度为 0 的点 |
| 非循环图 | 无向无回路 / 有向无半回路;反复删度 ≤ 1 的点能删成平凡图 |
| 连通的充分条件 | 简单图任两点度数和 ≥ n−1,或每点 d(v) ≥ (n−1)/2 ⇒ 连通 |
| 分支数与边数 | m ≤ (n−k)(n−k+1)/2,k−1 个孤立点 + Kn−k+1 取等 |
| 点割集 / 边割集 | 删掉后不连通,且少删任意一个都仍连通;单元素时叫割点 / 割边(桥) |
| 割点、割边 | v 是割点 ⇔ 存在 u、w,每条 u–w 路都过 v;e 是桥 ⇔ e 不在任何圈上 |
| Tarjan | 树枝边 (u,v) 是桥 ⇔ dfs[u] < low[v];复杂度 O(|V|+|E|) |
| 支配集 | 没选中的点都和选中的点相邻;无孤立点时,极小支配集的补集里还有另一个极小支配集 |
| 覆盖集 / 独立集(课件) | 都是边集:覆盖所有点的边 / 两两不相邻的边(匹配) |
| 点覆盖 | NP 难;2-近似:|A| = 2|E′| ≤ 2|OPT|;二部图上 = 最大匹配(König) |
| 欧拉图 | 连通图:欧拉图 ⇔ 所有点度为偶数 ⇔ 若干边不重的圈的并 |
| 欧拉链 | 连通且恰有两个奇点 u、v ⇔ 有 u 到 v 的欧拉链(加一条边 uv 化为欧拉回路) |
| 一笔画口诀 | 0 个奇点:回路;2 个奇点:链,从奇点出发;4 个以上:画不成 |
| 有向欧拉回路 | 弱连通且每点入度 = 出度 |
| Fleury | 沿未走过的边走,优先非桥边,除非只剩一条 |
| 中国邮递员 | 奇点两两配对沿最短路重复,取最小;管梅谷:每边至多重复一次,每个圈上重复边总权 ≤ 圈长一半 |
| 哈密顿图 | 有经过每点恰好一次的圈;NP 完全,无简单充要条件;回溯搜索 |
| Dirac / Ore | δ(G) ≥ n/2 ⇒ 哈密顿图;不相邻两点度和 ≥ n ⇒ 哈密顿图(n ≥ 3,简单图) |
| 定理 11.2.5 | 每对点度和 ≥ n−1 ⇒ 有哈密顿链 |
| 哈密顿必要条件 | 删去任意 k 个点,分支数 ≤ k(只能用来否定) |
| 课件运行结果 | 十二面体从 a 出发 162 条哈密顿通路,60 条可闭合;彼德森图共 240 条,0 条可闭合 |
易错点
- 自环对度数贡献 2;邻接矩阵对角线记 1 个自环,算度时要乘 2。
- 有向简单图允许 ⟨u,v⟩ 与 ⟨v,u⟩ 同时存在,它们不是平行边。
- 同构的必要条件(点数、边数、度数序列)只能用来否定同构。要肯定同构必须给出双射并验证。
- Wn 的下标在不同教材里指"总点数"或"圈上点数",先确认定义。
- 生成子图看"点全不全",导出子图看"选中点之间的边全不全"。
- 补图只对简单图定义,参照物是同阶的 Kn。
- 可达矩阵别忘了加 I,也别忘了最后布尔化;课件 Python 输出的大数是 (I+A)n−1 原值。
- 有向图的距离不对称,可达也不对称。
- "简单"管边不重复,"基本"管点不重复;基本 ⇒ 简单。
- 完备通路/回路允许点重复,它和"每个点恰好一次"的哈密顿通路/回路不是一回事。
- "G 有一条回路"指走法,"G 是回路"指图本身是一个圈(连通 2 度正则)。
- 有向图"没有有向回路"不等于"非循环图",后者要求连半回路都没有。
- "极小 / 极大"是不能再减 / 不能再加,"最小 / 最大"是个数最少 / 最多,前者不一定是后者。
- 点割集和边割集都要求"极小":删掉能断开,但少删任何一个都断不开。
- 有割点不一定有割边(领结图)。
- 本课件的覆盖集、独立集是边集;"最小点覆盖"是点集。看清选的是点还是边。
- Tarjan 判桥用 dfs[u] < low[v],判割点用 dfs[u] ≤ low[v](根结点另判)。
- 欧拉看边(每条边恰好一次,点可重复),哈密顿看点(每点恰好一次,边不必走完)。两者互不蕴含。
- "欧拉圈"允许点重复,不是 10.7 节"点不重复"的圈。
- 判断欧拉图前先确认连通;奇点个数一定是偶数,不会出现 1 个或 3 个。
- Fleury 里的"桥"是指剩余图(擦掉已走过的边)中的桥,不是原图中的桥。
- Dirac、Ore、定理 11.2.5 都是充分条件,不满足不代表不是哈密顿图(例如 Cn)。
- 度数和 ≥ n−1 只保证哈密顿链,≥ n 才保证哈密顿圈。