阅读 · 推演 · 自测 · 理解
WEEK 03 · STUDY NOTES

COMP3121 Week03 学习笔记

Greedy Algorithms 后续:最优排序、最优合并、图结构、最短路与最小生成树

主课件:PPT/From lecture/week2/2-greedy.pdf,PDF 实际 p37–153(全文件 154 页)周次说明:依用户要求将第二周录音范围之后的 PPT 内容编入 Week03;不是已核实的官方第三周讲授范围第二周录音仅用于划分边界,未把 p41–153 说成录音中的讲授内容
来源: 主课件:PPT/From lecture/week2/2-greedy.pdf,PDF 实际 p37–153(全文件 154 页), 周次说明:依用户要求将第二周录音范围之后的 PPT 内容编入 Week03;不是已核实的官方第三周讲授范围, 第二周录音仅用于划分边界,未把 p41–153 说成录音中的讲授内容
Module

01 · 本周地图:从局部选择到图上的全局结构

算法 / 主题:综合方法
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

这个部分回答什么问题:这份 PDF 的剩余内容怎样连成一条学习线?第二周笔记已用录音核对到基站覆盖的证明思路,并把 p37–38 作为自学补全。本页简短回顾这两页,重点新增 p41–153。文件存放在 week2 文件夹不代表全部属于第二周;这里的 Week03 是按你的学习编排命名,尚未核实学校正式周次。PDF 页脚编号通常比阅读器的实际页码小 1,本页的 p 均指实际页。

知识线PDF 实际页你要回答的问题
最优排序41–53为什么按文件长度、概率与期限排序?交换后目标值如何变化?
最优合并55–75为何反复合并最轻的两项,既节省合并代价又给出 Huffman 前缀码?
有向图结构78–110连锁激活如何转成 SCC、凝聚图的零入度点和拓扑序?
最短路径112–129Dijkstra 的暂定距离何时能定案,为什么非负边权不可省?
最小生成树131–153割边如何证明 Kruskal 安全,Union-Find 如何提速,又怎样得到最大间距聚类?

整页通用记号

10 个记号
xᵢ / xₖ
右下角是序号:第 i 或第 k 个对象的 x 值;不是 x 乘 i、k。
xₖ₋₁
第 k−1 个对象的 x 值,即第 k 个之前的那一个。
x′
读作 x prime,通常表示交换、更新或替换之后的新值;不是求导。
Σ / ∑
求和符号,把下标范围内的各项加起来;凝聚图记号 ΣG 另在对应章节解释。
∈ / ⊆ / V∖S
分别表示“属于”“是子集”“V 中去掉 S 后剩余的元素”。
→ / ⇝
→ 通常是一条直接的有向边;⇝ 表示可以沿多条边形成一条路径。
|V| / |E|
集合 V 的顶点数、集合 E 的边数;竖线表示集合大小。
∅ / ∞
空集合;无穷大。在最短路里 d=∞ 表示暂时不知道可达路径。
O(f(n)) / Θ(f(n))
渐近上界/同阶量级,用于说明输入规模增大时的运行时间。
≤ / ⇔
“小于或等于”/“当且仅当,两边互相推出”。

先认识通用写法,再看每节专用字母。相同字母可能被不同题目重复使用,不能跨章节套含义。

Module

02 · 基站证明的收尾:比较第 k 座的位置

算法 / 主题:基站覆盖
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

基站覆盖 · 原题

2-greedy.pdf · p33
Original English · Problem

Instance: Along the long, straight road from Balladonia (in the West) to Caiguna (in the East), houses are scattered quite sparsely, sometimes with long gaps between two consecutive houses. Telstra must provide mobile phone service to people who live alongside the road, and the range of Telstra’s cell tower is 5km. Task: Design an algorithm for placing the smallest number of cell towers alongside the road, that is sufficient to cover all houses.

中文翻译

输入:在从西部 Balladonia 通往东部 Caiguna 的一条笔直长路上,房屋分布稀疏,相邻两间房可能相距很远。Telstra 需要给路边居民提供移动通信服务,每座基站的覆盖半径为 5 公里。 任务:设计一种沿路放置基站的算法,在覆盖所有房屋的前提下,让基站数量最少。

课件 p33 的完整 Problem;p34 另假设 Caiguna 附近 5 公里内没有房屋,以暂避道路端点情况。

本节符号速查

5 个记号
h / h₁
h 是当前最西边尚未覆盖房屋的路上坐标;h₁ 是最初的第一间房。
gₖ
贪心方案第 k 座基站的中心坐标,越大表示越靠东。
aₖ
任意另一种合法方案按从西到东排后的第 k 座基站中心坐标。
k / r
k 是正在比较的基站序号;r 是贪心最终使用的基站总数。
R / 5
基站向左右各能覆盖的半径 R;课件取 R=5 公里。

aₖ≤gₖ 比较的是两方案同序号基站的位置,不是在说基站之间不能重叠。

基站覆盖:从最左未覆盖房屋向东放塔

看每座塔盖住的房屋,以及反设放得更东时漏掉的见证房屋。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:从第二周的最左未覆盖房屋算法,怎样推出塔数最少?设贪心第 k 座塔中心为 gₖ,任意可覆盖所有房屋的方案按从西到东排序后第 k 座为 aₖ。归纳命题是 aₖ≤gₖ:同样放到第 k 座时,贪心不会更靠西。

完整算法(半径 R):先按房屋位置从西到东排序;只要还有未覆盖的房屋,取最西边的那间 h,把新塔放在 h+R(道路端点有限时取允许范围内能覆盖 h 的最东点),标记覆盖区间,再继续。输出放置的塔数及位置。这个步骤确保每次既不漏掉 h,又尽量把右侧的新房纳入当前塔。

基例:第一间房在 h,任何方案的首塔若位于 h+R 以东便盖不到 h;贪心放在 h+R,故 a₁≤g₁。归纳:假设 aₖ₋₁≤gₖ₋₁。令 h 是前一贪心塔之后最西边未覆盖的房屋,则 gₖ₋₁+R<h=gₖ−R。若反设 aₖ>gₖ,便有 aₖ₋₁+R≤gₖ₋₁+R<h< aₖ−R;前 k−1 座替代塔到不了 h,第 k 座替代塔从 h 以东才开始覆盖,矛盾。这里 R=5 km 是课件数值;边界上的房屋算已覆盖,所以左边是严格小于。

若贪心共放 r 座,第 r 座照顾的那间房不能由任意 r−1 座合法方案覆盖,故至少需要 r 座。详细图解已放在第二周笔记;这里保留命题与结论,作为后面 greedy stays ahead 的参照。

基站:逐座领先的归纳证明

2-greedy.pdf · p37–38
Claim / Lemma

设 gₖ 是贪心方案第 k 座塔的位置,aₖ 是任意合法方案按从西到东排列后的第 k 座塔。对两方案都有第 k 座的每个 k,aₖ ≤ gₖ;据此证明贪心塔数最少。

Proof
  1. 基例 k=1

    令最西边的房屋位置为 h₁。半径为 5 km,贪心把首塔放在恰能覆盖它的最东位置;任何合法方案的首塔不能更东。

    g₁ = h₁ + 5;若 a₁ > g₁,则 a₁ − 5 > h₁,首间房未被覆盖。
    因此 a₁ ≤ g₁。
  2. 归纳假设

    设命题对第 k−1 座成立,即其他合法方案到这一步不比贪心更靠东。

    aₖ₋₁ ≤ gₖ₋₁。
  3. 归纳步 k≥2

    令 h 是第 k 座贪心塔要覆盖的最西边未覆盖房屋。前一贪心塔覆盖不到 h,贪心把新塔放在 h 东边 5 km;边界上的房屋算已覆盖,所以左侧是严格不等号。

    gₖ₋₁ + 5 < h = gₖ − 5。
  4. 反证

    若 aₖ > gₖ,则其他方案前 k−1 座塔的最东覆盖端仍在 h 左边,第 k 座及后续更东的塔的最西覆盖端在 h 右边。

    aₖ₋₁ + 5 ≤ gₖ₋₁ + 5 < h = gₖ − 5 < aₖ − 5。
  5. 推出最少塔数

    上式表明合法方案竟没有塔能盖到 h,矛盾,故 aₖ≤gₖ。若贪心用了 r 座,第 r 座的见证房屋 h 在前 r−1 座覆盖之外;任意仅有 r−1 座的方案也到不了 h,因此至少需要 r 座。r=1 时,至少有一间房,显然不能用零座塔。

    aᵣ₋₁ + 5 ≤ gᵣ₋₁ + 5 < h(r > 1)。
    最优塔数 ≥ r,而贪心恰用 r 座。

这是课件 p37–38 的归纳 Claim 与最终最优性证明;本页用 PDF 实际页码。

Module

03 · 磁带存储 I:短文件为何应该先放

算法 / 主题:磁带存储
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

磁带存储 I · 原题

2-greedy.pdf · p41
Original English · Problem

Instance: A list of n files of lengths Lᵢ which have to be stored on a tape. Each file is equally likely to be needed. To retrieve a file, one must start from the beginning of the tape and scan it until the file is found and read. Task: Order the files on the tape so that the average (expected) retrieval time is minimised.

中文翻译

输入:有 n 个长度分别为 Lᵢ 的文件,需要存到磁带上。每个文件被请求的概率相同。取出某个文件时,必须从磁带起点开始扫描,直至找到并读完它。 任务:安排文件在磁带上的顺序,使平均(期望)读取时间最短。

课件 p41 的完整 Problem;英文拼写保留课件原样。

本节符号速查

5 个记号
n
需要安排到磁带上的文件总数。
Lᵢ
排在磁带第 i 个位置的文件长度;排序后 i 表示当前位置。
Cᵢ
从磁带开头读到第 i 个文件末尾所需的时间,即前 i 个长度之和。
E
平均或期望读取时间;等概率时 E=(C₁+···+Cₙ)/n。
T / T′
T=nE 是交换前的缩放目标值;T′ 是交换相邻文件后的值。

这里的 Cᵢ 是读取完成时间;前缀码章节的 Cᵢ 会改指码字。

等概率磁带:消除长度逆序

逐步计算每个文件的结束位置和平均读取时间。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:文件读取必须从磁带开头顺序扫描、每个文件被请求的概率相同,怎样排列才能使平均读取时间最短?若排列后文件长度为 L₁,…,Lₙ,读到第 i 个文件的时间是前缀和 Cᵢ=Σⱼ₌₁ⁱLⱼ,因此 E=(1/n)Σᵢ₌₁ⁿ Cᵢ=(1/n)Σᵢ₌₁ⁿ(n−i+1)Lᵢ。n 是文件数,E 是期望读取时间;该式只适用于等概率请求、顺序扫描且完整读取目标文件的模型。

交换证明:若某个最优排列相邻两项出现 Lᵢ>Lᵢ₊₁,把它们交换,其他前缀与后缀的完成位置不变;缩放后目标 nE 的改变量是旧值减新值 Lᵢ−Lᵢ₊₁>0。这与原排列最优矛盾。因此最优排列没有相邻逆序,长度非递减。实际算法用高效排序,时间 O(n log n);证明里反复消除逆序并不要求真的用冒泡排序实现。

等概率磁带:相邻逆序交换证明

2-greedy.pdf · p42–45
Claim / Lemma

当 n 个文件被请求的概率均为 1/n 时,按长度 L₁≤L₂≤…≤Lₙ 存储使期望读取时间最小。

Proof
  1. 把期望展开

    从磁带开头读到第 i 个文件的时间是前缀和 Cᵢ;每个 Lᵢ 会出现在它自己及后面所有文件的读取时间里。

    Cᵢ = L₁ + ··· + Lᵢ。
    E = (1/n)Σᵢ₌₁ⁿ Cᵢ
      = (1/n)[nL₁ + (n−1)L₂ + ··· + 2Lₙ₋₁ + Lₙ]。
  2. 假设最优解仍有逆序

    如果排列不按长度非递减,必有一对相邻文件满足 Lᵢ>Lᵢ₊₁。令 T=nE;交换前后其他项的系数或完成位置都不变。

    T  = … + (n−i+1)Lᵢ   + (n−i)Lᵢ₊₁ + …
    T′ = … + (n−i+1)Lᵢ₊₁ + (n−i)Lᵢ   + …
  3. 计算目标变化

    交换后的缩放期望更小,与原排列“最优”矛盾。因此最优排列没有相邻逆序,也就是长度从短到长。

    T − T′ = Lᵢ − Lᵢ₊₁ > 0。
    E − E′ = (Lᵢ − Lᵢ₊₁)/n > 0。

交换只是正确性证明;课件建议实际用 mergesort 排序,时间 O(n log n)。

考题信号方法证明中的局部计算
每个请求等可能、前面长度会重复计入等待按 L 升序相邻长短逆序交换使 nE 减少 L长−L短

课件明确建议:真正实现文件排序用 O(n log n) 的 mergesort(归并排序),不要因为证明里交换相邻逆序就写 O(n²) 的冒泡排序。下面用同一组长度演示归并排序的“拆分→有序合并”。

归并排序在磁带题中的作用 · 课件算法原文

2-greedy.pdf · p45
Original English · Algorithm

Sort the files by increasing order of length using mergesort.

中文翻译

使用归并排序,按文件长度从小到大排列文件。

课件 p45 的 Algorithm 原文;归并排序负责真正排序,前面的相邻交换只用于证明顺序最优。

归并排序:真正把文件按长度排好

相邻交换是证明;实际可把文件列表递归拆开,再线性合并有序子列。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

Module

04 · 磁带存储 II:请求概率不同,按什么比值排序

算法 / 主题:磁带存储
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

磁带存储 II · 原题

2-greedy.pdf · p46
Original English · Problem

Instance: A list of n files of lengths Lᵢ and probabilities to be needed pᵢ, ∑ᵢ₌₁ⁿ pᵢ = 1, which have to be stored on a tape. To retrieve a file, one must start from the beginning of the tape and scan it until the file is found and read. Task: Order the files on the tape so that the expected retrieval time is minimised.

中文翻译

输入:有 n 个文件,文件 i 的长度为 Lᵢ,被请求的概率为 pᵢ,且 ∑ᵢ₌₁ⁿpᵢ=1。文件需要存放在磁带上;读取时必须从磁带开头扫描到目标文件并读完。 任务:安排文件顺序,使期望读取时间最短。

课件 p46 的完整 Problem;与上一题唯一关键变化是请求概率不再相等。

本节符号速查

5 个记号
Lᵢ
文件 i 的长度,必须大于 0,才能比较 pᵢ/Lᵢ。
pᵢ
文件 i 被请求的概率;所有文件的概率总和为 1。
Cᵢ
文件 i 在选定顺序中的结束位置,也是完整读到它的时间。
E
按请求概率加权的期望读取时间,E=ΣᵢpᵢCᵢ。
P
在相邻交换证明里,排在所比较两个文件之前的总长度。

pᵢ/Lᵢ 是“概率除以长度”的排序比值;这里的 P 不是后面 Dijkstra 增广堆的位置表。

不同请求概率:按 p/L 排序

把两种顺序的期望逐项相乘比较,看相邻交换到底改善多少。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:文件长短与被请求的概率都不同,先存哪一个?设文件 i 长度 Lᵢ>0、请求概率 pᵢ≥0,Σpᵢ=1。某排列的期望 E=ΣᵢpᵢCᵢ,其中 Cᵢ 是文件 i 在排列中的结束位置。规则是按 pᵢ/Lᵢ 从大到小排序;比值表示每单位扫描长度服务到的请求概率。

证明只看相邻 i、j。原顺序 i 再 j 与交换后 j 再 i 的其他文件贡献相同,旧 E−新 E=Lᵢpⱼ−Lⱼpᵢ。若 pᵢ/Lᵢ<pⱼ/Lⱼ,因长度为正,可交叉相乘得 Lᵢpⱼ>Lⱼpᵢ,交换严格改善期望。故任何最优序列都没有比值逆序。等比值时交换不改变 E,任选顺序。排序 O(n log n),扫描 O(n)。

不同概率磁带:p/L 比值的交换证明

2-greedy.pdf · p47–48
Claim / Lemma

长度 Lᵢ>0、请求概率 pᵢ≥0 且 Σpᵢ=1 时,按 pᵢ/Lᵢ 非递增排列使 E=ΣpᵢCᵢ 最小。

Proof
  1. 只看相邻两项

    设相邻文件为 i、j,它们之前的总长度是 P。它们后面文件的完成时刻不因两项交换而改变;比较两项自身贡献即可。

    Eᵢⱼ = pᵢ(P+Lᵢ) + pⱼ(P+Lᵢ+Lⱼ)。
    Eⱼᵢ = pⱼ(P+Lⱼ) + pᵢ(P+Lⱼ+Lᵢ)。
  2. 相减得到排序键

    把共同的 P、两项自己的长度和后缀贡献消去,交换改善多少只由交叉乘积决定。

    Eᵢⱼ − Eⱼᵢ = Lᵢpⱼ − Lⱼpᵢ。
  3. 消除比值逆序

    若前项比值更小,因为两项长度均为正,交叉相乘表明交换可严格减小 E。最优解不能含这种相邻逆序,故必须按 p/L 从大到小排;比值相同时可任意破平局。

    pᵢ/Lᵢ < pⱼ/Lⱼ
    ⇔ Lⱼpᵢ < Lᵢpⱼ
    ⇔ Eᵢⱼ − Eⱼᵢ > 0。

课件的目标是期望读取时间,而不是只让高概率文件排前;长度 Lᵢ>0 是交叉相乘的前提。

Module

05 · 最大延误:最早截止期为何优先

算法 / 主题:最大延误
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

最大延误 · 原题

2-greedy.pdf · p50
Original English · Problem

Instance: A list of n jobs, with lengths lenᵢ and deadlines dueᵢ. All jobs have to be completed, but only one job can be performed at any time. If a job i is completed at a finishing time finᵢ then we say that it has incurred lateness lateᵢ = finᵢ − dueᵢ. Task: Schedule all the jobs to minimise the largest lateness.

中文翻译

输入:有 n 个任务,任务 i 的处理时长是 lenᵢ,截止期是 dueᵢ。全部任务都必须完成,但任一时刻只能处理一个任务。若任务 i 在 finᵢ 完成,其延误定义为 lateᵢ=finᵢ−dueᵢ。 任务:安排所有任务,使最大的延误值尽可能小。

课件 p50 的完整 Problem;lateᵢ 为有符号的 lateness,提前完成时可为负。

本节符号速查

6 个记号
lenᵢ
任务 i 需要的处理时长。
dueᵢ
任务 i 的截止时刻(deadline)。
finᵢ
任务 i 的实际完成时刻。
lateᵢ
任务 i 的有符号延误,lateᵢ=finᵢ−dueᵢ;可为负。
t
交换的两项任务开始之前,机器已经工作到的时刻。
a / b
相邻交换证明中任务 i、j 的处理时长,分别等于 lenᵢ、lenⱼ。

本题目标是让 maxᵢ lateᵢ 最小;max 表示选出所有任务中最大的延误。

最大延误:交换截止期逆序

跟着任务时间轴算 fin−due,并比较交换前后的最大值。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:只有一台机器、所有任务都必须完成,怎样让最坏的延误尽可能小?任务 i 的处理时长为 lenᵢ、截止期为 dueᵢ,完成时刻为 finᵢ,课件定义有符号 lateness lateᵢ=finᵢ−dueᵢ;目标是最小化 maxᵢ lateᵢ。负数表示提前完成,不能随手改成 max(0,lateᵢ) 而不说明目标改变。任务中间留空只会推迟后续完成,所以存在没有空档的最优安排。

贪心规则是按 due 升序,即 earliest deadline first。证明:在某个最优顺序中找到相邻逆序 i、j,i 先于 j 但 dueᵢ>dueⱼ。设两任务之前的时间为 t。交换后 j 完成于 t+lenⱼ,不晚于原来完成于 t+lenᵢ+lenⱼ;i 交换后完成于 t+lenᵢ+lenⱼ,即原来 j 的完成时刻,但 dueᵢ>dueⱼ,所以新 lateᵢ≤原 lateⱼ。其他任务的完成时刻不变,整体最大延误不会升高。不断消除相邻逆序即可得到截止期排序。

最大延误:截止期排序的交换证明

2-greedy.pdf · p50–53
Claim / Lemma

一台机器、每次只做一个任务、所有任务都完成且不留空档时,按截止期 due 从早到晚排序可最小化 max lateᵢ,其中 lateᵢ=finᵢ−dueᵢ。

Proof
  1. 从任意最优顺序出发

    若它未按截止期排序,必有相邻逆序:i 在 j 前面,但 dueᵢ>dueⱼ。设这两项之前的时刻为 t,处理时长分别为 a、b。

    原顺序 i→j:finᵢ=t+a,finⱼ=t+a+b。
    交换顺序 j→i:fin′ⱼ=t+b,fin′ᵢ=t+a+b。
  2. 比较这两项的延误

    原来后做的 j 的延误大于原来 i 的延误;换后 j 提早完成,i 虽推迟,但截止期比 j 晚,因此仍不超过原 j 的延误。

    lateⱼ = t+a+b−dueⱼ > t+a−dueᵢ = lateᵢ。
    late′ⱼ = t+b−dueⱼ ≤ lateⱼ。
    late′ᵢ = t+a+b−dueᵢ < lateⱼ。
  3. 比较整体目标

    交换前后其他任务的完成时间不变,两项的最大延误不升,故整体最大延误不升。不断消除相邻逆序,终会得到截止期升序的一个最优顺序。

    max(late′ᵢ, late′ⱼ) ≤ lateⱼ = max(lateᵢ, lateⱼ)。
  4. 处理相同截止期

    课件最后指出:同截止期的任务互换,整组最后完成时刻不变,组内最大延误也不变。因此贪心对相同 due 任意破平局仍最优。

    若 dueᵢ=dueⱼ=d,则两项的最大延误
    = t+a+b−d,与这两项的先后无关。

这里的 lateness 可以为负;“时长不影响最优排序准则”并不是说时长不影响延误数值。

排序花 O(n log n),扫描计算累计时长与最大延误花 O(n)。若把目标改成平均完成时间、迟交任务数量、总加权延误,须重新求证,不能照搬截止期排序。

Module

06 · 三种最优排序题的同一证明骨架

算法 / 主题:最优排序
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

本节符号速查

3 个记号
i / j
正在比较的相邻两项的序号或名称。
逆序
两项相对于候选排序规则放反了,例如较长文件放在较短文件前。
E / E′
某题交换前后的目标值;具体目标可为读取时间或最大延误,须先看对应题目。

交换论证的关键不是记字母,而是分别写清交换前后目标值。

这个部分回答什么问题:看到排序型贪心题,怎样自己找出规则?先写清目标值对相邻两项的贡献,比较 i→j 和 j→i,消去不变的前后缀;若某种逆序总能交换而不变差,反复消除逆序后就得到排序规则。证明时必须说明交换不破坏可行性,以及整个目标而非某一项的改善。

目标相邻交换推出的顺序不能误推成
等概率磁带期望短长度先,L 升序只看最后一份文件的读取时间
不等概率磁带期望p/L 降序只按 p 或只按 L
单机最大有符号延误due 升序最短任务先,或总延误最小
Module

07 · 最优合并:同一项会被重复付费

算法 / 主题:最优合并
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

数组合并 · 原题

2-greedy.pdf · p55
Original English · Exercise

Assume you are given n sorted arrays of different sizes. You are allowed to merge any two arrays into a single new sorted array and proceed in this manner until only one array is left. Exercise: Design an algorithm which achieves this task and moves array elements as few times as possible. Give an informal justification why your algorithm is optimal.

中文翻译

给定 n 个大小各不相同的已排序数组。每次可以选择任意两个数组,将它们合并成一个新的已排序数组;不断合并,直到只剩一个数组。 练习:设计使数组元素总搬动次数尽可能少的算法,并非正式地说明为什么算法最优。

课件 p55 的完整 Exercise;这里的目标是累计元素搬动次数,而不是最终数组的长度。

本节符号速查

5 个记号
n / Lᵢ
n 是初始数组数目;Lᵢ 是第 i 个初始数组的长度。
x / y
某轮选来合并的两棵树或两个数组的当前长度。
T / T′
T 是完整的合并树;T′ 是把最深兄弟叶缩成一个叶子后的树。
depth_T(i)
第 i 个初始数组在树 T 中从根到叶所经过的边数。
Cost(T)
按合并树 T 操作时的总元素搬动次数,等于 ΣᵢLᵢ·depth_T(i)。

depth 越大,该初始数组被反复搬动的次数就越多。

最优合并:短数组先合

每轮把新长度放回候选集合;累计所有合并代价。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:把 n 个已排序数组两两合并成一个,怎样尽量少搬动元素?合并长度 x、y 的两个数组时,每个元素要移动一次,代价为 x+y;合并后的新数组长度也是 x+y,之后再次合并还会重复付费。把数组长度放入最小优先队列,每次取最短的两个合并,再把和放回队列,直到只剩一个。

把合并过程画成二叉树,原数组是叶子;一个原数组的长度会在从叶到根的每一层合并中付费。因此总成本是 Σᵢ Lᵢ×depth(i)。短数组可以放在较深的位置;对应的安全选择是存在一棵最优合并树,让两棵最轻子树先合并,再缩成一个新权重继续做。这里的完整论证与后面 Huffman 的兄弟交换、缩并归纳同构。

最优合并:课件练习的形式化补充

2-greedy.pdf · p55
Claim / Lemma

每次合并代价为两数组长度之和时,每轮合并当前最短的两个数组,得到最小总搬动代价。

Proof
  1. 把合并顺序转成树

    初始数组是叶子,合并操作是内部节点。长度 Lᵢ 的数组每经过祖先的一次合并便再付 Lᵢ,因此总成本等于叶子长度乘深度之和。

    Cost(T)=Σᵢ Lᵢ·depth_T(i)。
  2. 最短两叶可作最深兄弟

    取任一最优满二叉合并树的一对最深兄弟叶,把最短的两个数组交换到这两个位置。小长度承担更深的层数不会增加总成本;于是存在以最短两项先合的最优树。

    若 x≤y 且 D≥d,交换前后成本差
    Δ=(x−y)(D−d)≤0。
  3. 缩并并归纳

    把这对兄弟合为权重 x+y 的叶子;原问题成本比缩并问题多 x+y。若缩并结果不是较小问题的最优解,换成更好的树再展开会改进原树,矛盾。每轮都能安全地选最短两项。

    Cost(T)=Cost(T′)+(x+y)。

p55 只要求 informal justification;以上是利用 Huffman 同型树结构补全的正式证明,不是课件逐字给出的证明。

Module

08 · 前缀码:短编码必须仍能唯一解码

算法 / 主题:Huffman
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

前缀码 · 原题

2-greedy.pdf · p60
Original English · Problem

Problem: efficient, unambiguous code You are given a set of symbols, for example the English alphabet plus punctuation marks and a blank space (to be used between words), giving the 31 symbols: abcdefghijklmnopqrstuvwxyz ,.?! Each symbol has a frequency (probability of occurring). You want to encode these symbols using binary strings, so that sequences of such symbols can be decoded in an unambiguous way, and so that the expected length of the encoded text is minimised.

中文翻译

问题:高效且无歧义的编码。 给定一组符号,例如英文字母、标点符号和词间空格,共 31 个符号:abcdefghijklmnopqrstuvwxyz ,.?! 每个符号都有出现频率(概率)。要用二进制串给这些符号编码,使符号序列可被唯一解码,同时使编码文本的期望长度最小。

课件 p60 的完整 Problem;p56 先提出只要求无歧义的版本,本题进一步要求最短期望长度。

本节符号速查

4 个记号
Cᵢ
符号 i 的二进制码字,例如 Cₐ=00;这里不是磁带的完成时间。
len(Cᵢ)
码字 Cᵢ 含有多少个二进制位。
fᵢ
符号 i 在文本中出现的频率或概率。
L
平均码长,L=Σᵢfᵢ·len(Cᵢ),单位是每个符号的位数。

0、1 是二叉树左右边的标签;只有走到叶子才完成一个前缀码字。

前缀码:同一位串为何会有两个答案

读出 cake 与 cats 两种切法,再看前缀码怎样让边界确定。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:常见字符能否用短位串节约平均长度,同时保证消息只有一种解码?31 个符号用 5 位固定长度足够,因为 2⁵=32;按每 5 位切分自然无歧义,但高频与低频字符同样长。变长码若随意缩短,会出现某字符码字是另一个的前缀。

前缀码 prefix code 要求任一码字都不是另一码字的前缀。把 0、1 看成二叉树的左右边,所有符号只放在叶子;从根沿位串走,到叶子就确定一个符号,然后从根重新开始。不会在某个符号的叶子继续走向另一符号,因此这种码立即可解且无歧义。反向不成立:非前缀码不一定必然歧义,但课件的例子确实歧义。

优化目标是平均码长 L=Σᵢ fᵢ·len(Cᵢ),其中 fᵢ 是字符出现概率且总和为 1,Cᵢ 是其码字。例两个符号各 0.5,码字 0 与 1 的平均长为 0.5×1+0.5×1=1 位/符号;要比较的是概率加权长度,而不是最长码字。

Module

09 · Huffman:最轻两棵树反复合并

算法 / 主题:Huffman
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

Huffman · 课件算法原文

2-greedy.pdf · p64
Original English · Main idea

Make a priority queue of symbols, each weighted by its frequency. Repeatedly combine the two lowest frequency symbols. Remove the two symbols of lowest frequency, say x and y with frequencies fₓ and fᵧ. Make a new symbol xy with frequency fₓ + fᵧ, and insert it to the priority queue.

中文翻译

建立一个以符号频率为权重的优先队列。反复合并频率最低的两个符号:取出最低频的 x、y,频率分别为 fₓ、fᵧ;创建新符号 xy,频率为 fₓ+fᵧ,再将其插回优先队列。

课件 p64 没有另列新题,这里展示 Main idea 原文;它解决上一节 p60 的编码题。

本节符号速查

4 个记号
fₓ / fᵧ
本轮频率最低的两个候选符号或子树 x、y 的权重。
xy
把 x、y 合并得到的新内部节点;其权重为 fₓ+fᵧ。
n
需要编码的不同符号个数。
L
最终码树的平均码长,符号频率乘码字长度后求和。

合并后的 xy 不是普通文本里的两个连续字母,而是优先队列中的一棵新子树。

Huffman:最轻两项反复合并

按照课件频率逐步看优先队列变化;最后显示一棵有效码树。

可单步、回退、重置;自编实例帮助观察状态,不能代替一般正确性证明。

这个部分回答什么问题:如何构造平均位数最短的前缀码?Huffman 把每个字符作为一棵权重为频率 f 的树;用最小优先队列取出权重最小的两棵树 x、y,新建父结点权重 fₓ+fᵧ,左边记 0、右边记 1,再放回队列。直到只剩根;从根到叶的 0/1 路径就是该字符码字。每轮只做一次局部合并,但其正确性还需后面的最优兄弟性质。

轮次取出的最轻两项放回的合并权重仍在队列中的权重(示意)
初始a=.32,b=.25,c=.20,d=.18,e=.05—.05,.18,.20,.25,.32
1e=.05 与 d=.18de=.23.20,.23,.25,.32
2c=.20 与 de=.23cde=.43.25,.32,.43
3b=.25 与 a=.32ab=.57.43,.57
4cde=.43 与 ab=.57根=11

课件的一个合法分支编号得到 a=00、b=01、c=11、d=100、e=101。平均码长 L=0.32×2+0.25×2+0.20×2+0.18×3+0.05×3=2.23 位/符号。左右子树交换会改变具体码字,但不会改变叶深度和平均长度。

Module

10 · Huffman 为什么最优:最深兄弟与缩并

算法 / 主题:Huffman
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

Huffman 最优性 · 课件命题原文

2-greedy.pdf · p75
Original English · Lemma

Given the frequency fᵢ of each symbol i, the Huffman code produces an optimal prefix code.

中文翻译

给定每个符号 i 的频率 fᵢ,Huffman 编码会产生一组最优前缀码。

课件 p75 的 Lemma 原文;本节下方 Proof 框展开课件的三步证明提纲。

本节符号速查

6 个记号
T / T′
T 是原最优码树;T′ 是把最轻兄弟叶 x、y 缩成一个叶后的树。
fᵢ
符号 i 的频率;fₓ、fᵧ 是频率最小的两项。
depth_T(i)
在码树 T 中,从根走到符号 i 的叶子所经边数,即码字长度。
D / dₓ
交换论证中目标最深叶的深度 D,以及 x 原来所在叶的深度 dₓ。
Δ
交换后的目标值减交换前的目标值;Δ≤0 表示不会变差。
OPT(n)
含 n 个符号时可以达到的最小平均码长。

证明中的 x、y 是符号;下一节坐标 (xᵢ,yᵢ) 的 x、y 则是平面坐标轴。

Huffman 证明:交换最轻叶并缩并

区分运行过程与正确性证明;观察 Σf·depth 如何变为同型子问题。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:为什么可以放心先合并频率最小的两字符?一棵最优前缀码树可以视为满二叉树:若内部结点只有一个孩子,直接删去该结点会缩短其子树码字而不破坏前缀性。满树中取一对最深的兄弟叶;把最低频的两个符号交换到这对叶子上,目标 Σf·depth 不会上升,因为较小频率承担较大的深度更划算。

设最低频为 fₓ、fᵧ。在这样一棵最优树中,把兄弟 x、y 收缩为权重 fₓ+fᵧ 的新叶,得到规模 n−1 的问题;原树的平均码长 = 缩并树的平均码长 + fₓ+fᵧ,因为 x、y 的路径各少一条边。若缩并树不是 n−1 问题的最优树,换成更好的树再展开 x、y,便能改善原树,矛盾。归纳得到每轮最轻两项合并的正确性。

Huffman 最优性:课件三步证明提纲的展开

2-greedy.pdf · p75
Claim / Lemma

给定每个符号频率 fᵢ,Huffman 每轮合并频率最小的两棵树,最终得到最小化 L(T)=Σᵢfᵢ·depth_T(i) 的前缀码。

Proof
  1. 最优树可以是满二叉树

    前缀码符号只在叶子;若内部节点只有一个孩子,删掉它并把孩子上提,仍是前缀码且有关叶子的深度减少。所以可在满二叉树中寻找最优解。

    L(T)=Σᵢ fᵢ·depth_T(i)。
  2. 最轻两符号可放到最深兄弟处

    满二叉树的一片最深叶有一个同样最深的兄弟。取频率最低的 x、y,把它们分别与占据这两个位置的符号交换;较低频率移到更深位置,目标不会上升。由此至少存在一棵最优树令 x、y 为最深兄弟。

    设 fₓ≤fₐ,D≥dₓ:
    Δ=(fₓ−fₐ)(D−dₓ)≤0;y 同理。
  3. 缩并为同型子问题

    把兄弟 x、y 缩成一个权重为 fₓ+fᵧ 的新叶。展开会让两者深度各增加 1,其余叶深度不变。

    L(T)=L(T′)+fₓ+fᵧ。
  4. 对符号数归纳

    n=2 时两符号各用一位即最优。对 n>2,若缩并树非 n−1 符号问题的最优树,用更优树替换并展开会与原树最优矛盾。归纳假设说明较小问题可由 Huffman 最优解决,故原问题也可。

    OPT(n)=OPT(n−1; fₓ+fᵧ)+(fₓ+fᵧ)。

课件 p75 给出 full binary tree → 最深兄弟 → 缩并归纳的 outline;交换差值和递推式是为自学补全的推导。

Module

11 · 海啸预警:位置与半径先转成有向关系

算法 / 主题:强连通分量
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

海啸预警 · 原题

2-greedy.pdf · p78
Original English · Problem

Instance: There are n radio towers for broadcasting tsunami warnings. A tower i has coordinates (xᵢ, yᵢ) and a range rᵢ. You need to equip some of these towers with seismic sensors. When there is a tsunami risk, all towers with sensors activate and each activated tower also activates all towers within its range, and so on. Task: Design an algorithm that finds the smallest number of towers you must equip with seismic sensors so that all towers become activated.

中文翻译

输入:有 n 座用于广播海啸警报的无线塔。塔 i 的坐标为 (xᵢ,yᵢ),通信半径为 rᵢ。需要在部分塔上安装地震传感器。发生海啸风险时,装有传感器的塔先启动;每座已启动塔又会启动其覆盖范围内的其他塔,如此持续传播。 任务:设计一种算法,找出为使所有塔最终启动而必须安装传感器的最少塔数。

课件 p78 的完整 Problem;后面的 SCC 与凝聚图均服务于这一题。

本节符号速查

4 个记号
n / i
无线塔总数;i 是其中一座塔的编号。
(xᵢ,yᵢ)
塔 i 在平面上的位置坐标,分别是横坐标与纵坐标。
rᵢ
塔 i 的广播半径;不同塔可以有不同半径。
u→v
塔 u 可以直接激活塔 v;反向 v→u 不一定存在。

坐标 xᵢ、yᵢ 是位置,不是 Huffman 证明中最低频的符号 x、y。

海啸预警:从广播半径到有向激活

相同的三座塔,从不同起点能沿有向路径激活不同集合。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

课件七塔覆盖图:g 独立,a、b、c、d 在中部重叠覆盖圆附近,e、f 在右侧;虚线圆是各塔自己的广播范围
课件 PDF 实际 p80 的七塔覆盖示意(原图局部)。先从每座塔的虚线圆读出单向激活,再找可互达的 SCC;颜色不是 SCC 的定义。

课件 p79–80 的七塔图用虚线圆表示每座塔自己能直接广播到的区域,染色帮助观察一轮连锁激活。读图时先看“某塔的圆里有哪些塔”,画从该塔指向那些塔的箭头,再沿箭头继续传。红、蓝、绿只是这个示意的颜色;不能直接把同色点当作同一个 SCC,必须额外检查能否沿箭头返回。g 与其他塔分离,更容易看出它需要独立启动。

这个部分回答什么问题:给部分广播塔安装传感器,使报警沿无线激活关系传到每座塔,传感器最少要几个?塔 i 有位置 (xᵢ,yᵢ) 与半径 rᵢ;若塔 j 到 i 的欧氏距离不超过 rᵢ,就连有向边 i→j。一个装传感器的塔启动后,所有沿有向路径可达的塔最终都会启动。建图时可用 (xᵢ−xⱼ)²+(yᵢ−yⱼ)²≤rᵢ² 判断直接边;例 (0,0)、半径 5 的塔能直接激活 (3,4) 的塔,因为 3²+4²=5²。一般位置下检查所有有序塔对花 O(n²)。

只看半径最大或直接覆盖塔数最多,会忽略多步激活和方向。课件把它们作为待找反例的候选策略。自编的一维可实现例:A 在 x=0、r=2;B 在 x=1、r=1;C 在 x=3、r=2。A、C 的半径和直接覆盖数量都并列最高;若任意破平局先选 A,可激活 A、B,却到不了 C,还需第二个传感器。选 C 会先到 B,B 再到 A,只需一个。此例足以推翻两种“任意破平局都正确”的规则。

正确的结构信号是互相可达:若一组塔内任意两座都能沿路径相互激活,那么这一组只需考虑装一个传感器,并可把整组缩成一座“超级塔”。这就是下一节强连通分量。

Module

12 · SCC:双向可达才是一座“超级塔”

算法 / 主题:强连通分量
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

强连通分量 · 课件问题与命题

2-greedy.pdf · p89
Original English · Question / Claim

How do we find the strongly connected component Cᵥ ⊆ V containing v? Claim: u is in Cᵥ if and only if u is reachable from v and v is reachable from u.

中文翻译

如何找出包含顶点 v 的强连通分量 Cᵥ⊆V? 命题:u 属于 Cᵥ,当且仅当 v 可以到达 u,且 u 也可以到达 v。

课件 p89 的 Question 与 Claim;本页不是新的独立优化题,而是 p78 海啸题的子问题。

本节符号速查

6 个记号
G=(V,E)
有向图 G;V 是所有塔对应的顶点集合,E 是可直接激活的有向边集合。
u / v
正在比较的两个顶点。
Cᵥ
包含顶点 v 的强连通分量,即与 v 可以双向沿路径到达的一组点。
Rᵥ / R′ᵥ
分别是在原图 G、反图 Gʳᵉᵛ 中从 v 出发可到达的顶点集合。
Gʳᵉᵛ
反图:保留所有顶点,把原图的每条有向边反转。
v⇝u
从 v 到 u 存在一条有向路径;可能经过不止一条边。

同时属于 Rᵥ 和 R′ᵥ 才代表双向可达,只有一条直接反向边不是必要条件。

SCC 入门:两次可达取交集

正向可达与反向可达都满足,才属于同一强连通分量。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:如何精确找出可以互相替代的塔群?有向图 G=(V,E) 中,顶点 v 所在的强连通分量 Cᵥ 包含所有同时满足 v⇝u 与 u⇝v 的顶点 u。它是极大集合,不只是某一个环:多个环可共享顶点并合成更大的 SCC。

一次概念上最直接的求法:在原图从 v 做 BFS/DFS,得 Rᵥ(v 能到达的点);把所有边反向得 Gʳᵉᵛ,在反图从 v 做 BFS/DFS,得 R′ᵥ(原图中能到达 v 的点);交集 Cᵥ=Rᵥ∩R′ᵥ。课件例子从 e 得 Rₑ={d,e,f,g,h},R′ₑ={a,b,c,d,e,f},交集是 {d,e,f};另两组是 {a,b,c} 与 {g,h}。

{a,b,c}{d,e,f}{g,h}零入度源 SCC
按课件 p93、p102 的 SCC 分组与凝聚关系重绘。缩点后只需在零入度源分量内安装一座传感器。

若对每个 v 都独立做两次遍历,最坏 O(|V|(|V|+|E|));这个交集法适合解释定义,计算全部 SCC 应用线性时间的 Tarjan 或 Kosaraju,均为 O(|V|+|E|)。这里 |V|、|E| 分别是顶点、边数。

Module

13 · 线性时间 SCC:Tarjan 的栈与 low 值

算法 / 主题:强连通分量
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

Tarjan · 课件算法原文

2-greedy.pdf · p97
Original English · Algorithm sketch

Do a DFS with an additional stack. Each vertex v also maintains an id between 0 and n−1, assigned in the order the vertices are encountered by the DFS, a low value, which is the smallest id of a vertex that can be reached from v using DFS edges plus one back-edge, and a Boolean in-stack which is true if the vertex is on the stack. After having visited all neighbours of a vertex v, if v.low = v.id, then pop all vertices from the stack up to and including v; these form one strongly connected component.

中文翻译

在 DFS 之外维护一个栈。每个顶点 v 还记录:按 DFS 首次访问顺序分配的 id(0 到 n−1);low 值,即从 v 沿 DFS 边并最多经一条回边可到达的最小 id;以及表示 v 是否在栈中的布尔值。访问完 v 的所有邻点后,若 v.low=v.id,就从栈顶一直弹到 v(含 v);弹出的点组成一个强连通分量。

课件 p97 只给 Tarjan 的 sketch,没有独立题目;这里保留其关键算法原句与对应翻译。

Kosaraju · 课件算法原文

2-greedy.pdf · p98
Original English · Algorithm statement

Kosaraju’s algorithm (presented in CLRS §22.5) is an alternative. It involves two executions of DFS. More complicated to reason about, easier to implement in code. It also runs in linear time, i.e., O(|V|+|E|).

中文翻译

Kosaraju 算法(见 CLRS §22.5)是另一种方法。它需要执行两次 DFS;正确性较难推理,但更容易写成代码。其运行时间同样为线性时间 O(|V|+|E|)。

课件 p98 仅有以上概述;本页正文中的具体两轮执行步骤属于标明的自学补全。

本节符号速查

5 个记号
id[v]
顶点 v 被 DFS 首次访问时分配的顺序编号。
low[v]
沿当前 DFS 分支并通过栈内回边能够追溯到的最小访问编号。
in-stack
布尔状态:顶点是否仍留在候选 SCC 的栈中。
p / c
DFS 树中的父顶点 p、子顶点 c;回退时用 c.low 更新 p.low。
Gʳᵉᵛ
Kosaraju 第二轮使用的反向图,所有有向边方向与 G 相反。

这里的 stack 是尚未输出 SCC 的候选顶点栈;low 不是顶点的编号本身。

Tarjan:id、low、候选栈逐步变化

逐条看 DFS 树边、指向栈内点的边、返回与弹出 SCC。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:怎样避免为每个顶点重跑搜索?Tarjan 做一次 DFS,给顶点发现序号 id,维护仍在候选 SCC 栈中的状态,以及 low:从当前 DFS 子树沿已探索的有向边能够回到的、仍在栈中的最早发现序号。子结点返回时用 low[父]=min(low[父],low[子]) 传播;遇到指向栈内顶点的边时用该顶点 id 更新。只有对仍在栈中的目标进行回边更新;已经弹出的 SCC 不应被并入当前 SCC。

Tarjan 操作顺序(补足课件的 sketch):首次访问 v 时赋 id[v]=low[v]=下一发现序号并压入候选栈;遇未访问的孩子 w 先递归,再令 low[v]=min(low[v],low[w]);遇已访问且仍在候选栈中的 w,令 low[v]=min(low[v],id[w]);已弹栈的 w 不能拿来更新 low。处理完所有出边后若 low[v]=id[v],从栈顶弹到 v,弹出的就是一个 SCC。若图不连通,对每个尚未访问的点启动 DFS。

当一个 DFS 根 v 满足 low[v]=id[v],从栈顶弹到 v 的所有顶点组成一个 SCC。每点入栈出栈各一次、每边检查常数次,总 O(|V|+|E|)。另一条课件路线 Kosaraju 做两轮 DFS:用第一轮的完成顺序安排第二轮在反图搜索,同样线性。

Kosaraju 是课件提到的另一条路线,下面把实现步骤补全:在原图 G 对全部顶点做 DFS,记录每点完成时间;构造反图 Gʳᵉᵛ;按原图完成时间从晚到早,在反图对尚未分组的点做 DFS,每次搜索到的一组就是一个 SCC。可直观理解为:第一轮决定从哪些分量开始,反向后跨分量边不能把当前搜索带到尚未处理的分量。两轮 DFS 与反图构造总 O(V+E)。

Kosaraju:完成顺序与反图第二轮

同一张图两轮 DFS,第二轮在反图依完成时间逆序分组。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

Module

14 · 凝聚图与最少传感器:数零入度 SCC

算法 / 主题:强连通分量
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

凝聚图 · 课件命题原文

2-greedy.pdf · p103
Original English · Claim

The condensation graph ΣG is a directed acyclic graph.

中文翻译

凝聚图 ΣG 是有向无环图(DAG)。

课件 p103 的 Claim;该页没有单独的新题,仍在解决 p78 的海啸预警题。

最少传感器 · 课件解法原文

2-greedy.pdf · p104
Original English · Solution

The correct greedy strategy is to only place a sensor in each super-tower without incoming edges in the condensation graph.

中文翻译

正确的贪心策略是:只在凝聚图中每个没有入边的“超级塔”(强连通分量)内放置一座传感器。

课件 p104 的 Solution 原文;紧随其后的 Proof 框给出下界与可行性证明。

本节符号速查

5 个记号
ΣG
图 G 的凝聚图:每个 SCC 缩成一个“超级顶点”;这里的 Σ 不表示求和。
U / W
凝聚图中的两个 SCC;若原图有跨分量边,就可记 U→W。
入度
有多少条边从别的 SCC 指向某个 SCC;零入度的叫源 SCC。
DAG
directed acyclic graph,有向无环图;凝聚图一定是 DAG。
s
源 SCC 的数量;最少需要的传感器数恰好也是这个数量。

“源”在本节指零入度分量;Dijkstra 的 s 则是指定的最短路起点。

最少传感器:零入度 SCC 的下界与构造

每个源分量不得不选一座;选择后又确实能激活全图。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:得到 SCC 之后怎么选传感器?将每个 SCC 缩成一个顶点,若原图有跨 SCC 的边 U→W,就在凝聚图中连边 U→W(重复边只算一次)。凝聚图必是有向无环图 DAG,否则环上的各 SCC 可合并,违反它们的极大性。课件例子缩成 {a,b,c}→{d,e,f},并且两者可到 {g,h}。

答案是在凝聚图每个入度为 0 的 SCC 中任选一座塔装传感器。下界:零入度 SCC 不能从其他 SCC 激活,因此每个至少要一个。上界:任意 SCC 沿入边不断往前走,在有限 DAG 中必到达某个零入度 SCC;该源点安装的传感器沿有向路径可激活它。所以传感器数恰好等于零入度 SCC 个数。课件例中只有 {a,b,c} 是零入度,因此装一个即可。

凝聚图必为 DAG:反证

2-greedy.pdf · p103
Claim / Lemma

将有向图每个强连通分量缩成一个顶点得到凝聚图 ΣG,则 ΣG 不含有向环。

Proof
  1. 反设有环

    假设 ΣG 中不同分量 C₁→C₂→…→Cₜ→C₁ 构成有向环。

  2. 环上互相可达

    沿环从任意 Cᵢ 到任意 Cⱼ 都有路径;再沿环可返回。原图里这些分量中的顶点因此两两互相可达。

    Cᵢ ⇝ Cⱼ 且 Cⱼ ⇝ Cᵢ。
  3. 违反 SCC 极大性

    环上的所有 Cᵢ 应当合成同一个更大的 SCC,与它们原本是不同的极大强连通分量矛盾。故凝聚图无环。

这是课件 p103 的 Proof Outline;第二步展开了“可合并”的理由。

传感器最少:下界与达到下界

2-greedy.pdf · p104
Claim / Lemma

在凝聚 DAG 的每个零入度 SCC 中安装一座传感器,恰好得到使所有塔激活的最少传感器数。

Proof
  1. 下界:每个源 SCC 都必须选

    零入度 SCC 无法由其他 SCC 激活;要让其中的塔启动,必须在这个分量内部至少装一座。不同源分量分别需要一座。

    任何合法解的传感器数 ≥ 零入度 SCC 的数量。
  2. 上界:这些源 SCC 足够

    取任意非源 SCC,沿入边逆向走。凝聚图有限且无环,过程不能无限继续,必到某个零入度 SCC。沿原方向从该源 SCC 能逐步激活当前分量。

    每个 SCC 都能从某个源 SCC 沿有向路径到达。
  3. 上下界相等

    在所有源 SCC 各放一座既合法又达到不可突破的下界,因此最优。

    最少传感器数 = 零入度 SCC 的数量。

本证明对应课件 p104;“先证明不得不选,再证明选完足够”是关键两半。

算法流程:由坐标与半径建图 → 求全部 SCC → 扫描跨分量边,标记有入边的分量 → 对每个未标记分量选一座塔。若输入已经给了图,后半部分 O(|V|+|E|);若从 n 座塔的坐标显式建图,检查塔对的 O(n²) 往往主导。不要把“线性图算法”误报成从坐标输入开始的总 O(n)。

Module

15 · 拓扑排序与 Kahn:每轮删除一个零入度点

算法 / 主题:拓扑排序
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

Kahn 拓扑排序 · 课件算法原文

2-greedy.pdf · p109
Original English · Question / Algorithm

How do we topologically order the vertices? Maintain a list L of vertices, initially empty, an array D consisting of the in-degrees of the vertices, and a set S of vertices with no incoming edges. While set S is non-empty, select a vertex u with D[u] = 0 in the set. Remove it from S and append it to L. Then, for every outgoing edge e = (u, v) from this vertex, remove the edge from the graph, and decrement D[v] accordingly. If D[v] is now zero, insert v into S. If there are no edges remaining, then L is a topological ordering. Otherwise, the graph has a cycle.

中文翻译

怎样给图的顶点做拓扑排序? 维护初始为空的顶点列表 L、记录各顶点入度的数组 D、以及当前零入度顶点集合 S。只要 S 非空,取出其中一个 D[u]=0 的顶点 u,移出 S 并加入 L。然后对 u 的每条出边 (u,v),从图中删除该边,并将 D[v] 减一;若 D[v] 变为零,则把 v 加入 S。若最后没有边剩余,L 就是拓扑序;否则图存在有向环。

课件 p109 的 Question 与完整 Algorithm;无单独数值型优化目标。

本节符号速查

5 个记号
G=(V,E)
待拓扑排序的有向图;V 为顶点集合,E 为有向边集合。
σ(v)
顶点 v 在最终线性排列中的位置;u→v 要求 σ(u)<σ(v)。
D[v]
Kahn 算法中顶点 v 在当前剩余图里的入度,删边后要更新。
S / L
S 是当前零入度顶点集合;L 是已经输出的拓扑序列表。
u→v
有向边,表示 u 必须排在 v 前面。

D[v] 是入度数组,不是下一章 Dijkstra 的暂定距离 d[v]。

Kahn 拓扑排序:动态维护剩余入度

观察零入度队列如何随着删边改变,不把原始入度当作固定排序键。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:DAG 上如何安排一个尊重所有有向边的处理顺序?拓扑序是顶点排列 σ,使每条 u→v 都满足 σ(u)<σ(v)。DAG 至少有一个拓扑序,可能不唯一;有向环不可能有,因为沿环会要求位置严格递增后又回到起点。

Kahn 算法:预先算每点入度,把所有零入度点放入集合或队列 S;每轮从 S 取一个加入结果 L,视作删去它的出边,并把因此入度变成 0 的邻居加入 S。若输出 |V| 个点,L 是拓扑序;若提前停下但还有顶点,剩余部分含有有向环。初始化和每条边的入度递减各一次,总 O(|V|+|E|)。

可直接照着实现:indegree[v] 先数入边;把所有 indegree=0 的点入队。循环取队首 u,写入输出;对每条 u→v 使 indegree[v] 减 1,刚变成 0 才入队。结束时检查输出数:等于 |V| 就是拓扑序,否则剩余图中有环。边只会在删除其起点时处理一次。

Module

16 · Dijkstra:暂定距离与已定案集合

算法 / 主题:Dijkstra
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

单源最短路 · 原题

2-greedy.pdf · p112
Original English · Problem

Instance: a directed graph G = (V, E) with non-negative edge-weights w(e), and a designated source vertex s ∈ V, such that for every v ∈ V there is a path from s to v. Task: for each v ∈ V, find the smallest weight of a path from s to v.

中文翻译

输入:有向图 G=(V,E),每条边的权重 w(e) 非负,给定源点 s∈V,并假设从 s 到每个顶点 v∈V 都存在路径。 任务:对每个 v∈V,求从 s 到 v 的路径的最小权重。

课件 p112 的完整 Problem;Dijkstra 后续证明和数据结构均围绕此题。

本节符号速查

6 个记号
s
指定的源点,所有路径都从 s 出发。
S
已经“定案”的顶点集合;其中各顶点的最短距离已确定。
d[v]
当前从 s 到 v 的最短已知候选路径长度;定案前可能下降。
w(e)
有向边 e 的权重或长度,本题要求 w(e)≥0。
v / z
v 是本轮取出的未定案顶点;z 是它某条出边指向的邻点。
∞
尚无已知 s→v 路径时的暂定距离,不是一个普通有限边权。

从一条候选路径的长度到真正最短路,还需要下一节的正确性证明。

Dijkstra:暂定距离逐步定案

自编五点有向图。绿色顶点已定案;每步观察选出的点、松弛结果与距离表。

可单步、回退、重置;自编实例帮助观察状态,不能代替一般正确性证明。

这个部分回答什么问题:从一个起点 s 到每个顶点的最短路径长度怎么找?课件输入是有向图 G=(V,E)、非负边权 w(e)≥0,并假定 s 可达所有顶点。维护 S:最短距离已证实的顶点集合;d[v]:从 s 到 v、内部顶点只用 S 的已知最短候选路径长度。初始 d[s]=0,其他为 ∞,S 为空。每轮从 V\S 中取 d 最小的 v 加入 S,并检查 v 的出边。

完整迭代:令所有 d=∞、d[s]=0、S=∅;重复取未定案且 d 最小的 v;若最小值已是 ∞,剩余顶点不可达并停止;否则把 v 加入 S,并对每条 v→z 且 z 不在 S 的边做 d[z]←min(d[z],d[v]+w(v,z))。直到所有可达点定案。若要复原最短路,只有严格改善 d[z] 时才记 parent[z]=v。

这里的“不知道”表示暂定距离可能还会下降;一旦顶点进入 S,d[v] 就等于真正的最短距离。例 s→a 权重 4、s→b 权重 1、b→a 权重 2:先看 s 的出边得 d[a]=4、d[b]=1,随后取 b 并更新 d[a]=3。因而不能把第一次发现 a 的路径直接定案。

Module

17 · Dijkstra 的安全选择:第一条离开 S 的边

算法 / 主题:Dijkstra
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

Dijkstra 正确性 · 课件命题原文

2-greedy.pdf · p115
Original English · Claim

Suppose v is the next vertex to be added to S. Then dᵥ is the length of the shortest path from s to v.

中文翻译

设 v 是下一步要加入集合 S 的顶点。那么 dᵥ 就是从 s 到 v 的最短路径长度。

课件 p115 的 Claim;没有新的题目,沿用 p112 的单源最短路原题。

本节符号速查

5 个记号
S
本轮开始时已定案的顶点集合。
v / y
v 是本轮要定案的点;y 是反设的更短路径第一次离开 S 时碰到的点。
p / p′
p 是当前长度为 d[v] 的已知候选路径;p′ 是反设存在的更短路径。
d[v] / d[y]
只允许旧 S 作中间顶点时,到 v、y 的最短已知候选长度。
w(p′)
路径 p′ 上所有边权之和;w(p′[s→y]) 只算从 s 到 y 的前缀。

这里的小写 p 是路径,不是磁带题的概率 pᵢ,也不是堆的位置表 P[i]。

Dijkstra 安全性:替代路径第一次离开 S

沿路径找 y,逐段读出 d[v]≤d[y]≤整条路径长度。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:为什么总可以把暂定距离最小的 v 定案?归纳不变式:S 中每点 d 等于真正最短距离;S 外每点 d 是内部顶点只取自 S 的最短候选距离。设本轮选择 v,假如有比 d[v] 更短的 s→v 路径 P,令 y 是 P 上第一个不在 S 的点。P 到 y 的前缀内部顶点全在 S,故前缀长度至少 d[y]。边权非负,所以整条 P 的长度至少这个前缀长度;而贪心选 v 保证 d[v]≤d[y]。于是 P 的长度不可能小于 d[v],矛盾。

Dijkstra 定案:首次离开 S 的路径证明

2-greedy.pdf · p115–117
Claim / Lemma

当边权非负,且 v 是本轮 S 外 d 值最小的顶点时,d[v] 等于从源点 s 到 v 的真正最短路径长度。

Proof
  1. 当前候选路径

    按 d 的定义,存在一条从 s 到 v、内部顶点只取自 S 的已知路径 p,长度为 d[v]。第一次选到的 v=s,d[s]=0,显然成立。

  2. 反设有更短路径

    若另一条 s→v 路径 p′ 更短,令 y 为 p′ 上第一个不在 S 的顶点。p′ 到 y 的前缀内部顶点均在 S,因此该前缀是 d[y] 考虑过的候选之一。

    d[y] ≤ w(p′[s→y])。
  3. 用非负边权与贪心选择夹住路径

    p′ 从 y 到 v 的剩余边权之和非负;v 是 S 外 d 最小的点,所以 d[v]≤d[y]。

    d[v] ≤ d[y] ≤ w(p′[s→y]) ≤ w(p′)。
  4. 矛盾并维持不变式

    上式说明 p′ 不可能短于 d[v],与反设矛盾。因此 v 定案正确;把 v 加入 S 后,下一节的松弛会维护 S 外 d 的定义。

非负边权直接用于最后一个 ≤。若存在负边,整条路径可能短于到 y 的前缀,证明不成立。

数值感受:若当前 d[v]=4、某条替代路径首次离开 S 时 d[y]=5,那么后续每条边非负,整条替代路径至少 5,不能把 v 的 4 推翻。若后续可以出现权重 −3,则路径可能从 5 降到 2,证明断裂。这里的 4、5、−3 是说明不等式的自编数值,不是课件图上的标号。

Module

18 · 松弛:加入 v 后只检查它的出边

算法 / 主题:Dijkstra
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

Dijkstra 松弛 · 课件问答原文

2-greedy.pdf · p118
Original English · Question / Answer

Question: Earlier, we said that when we add a vertex v to S, we may have to update some d_z values. What updates could be required? Answer: If there is an edge from v to z with weight w((v, z)), the shortest known path to z may be improved by taking the shortest path to v followed by this edge. Therefore, we check whether d_z > d_v + w((v, z)), and if so we update d_z to the value d_v + w((v, z)).

中文翻译

问题:前面说把顶点 v 加入 S 后,可能要更新某些 d_z;需要做哪些更新? 回答:若存在从 v 到 z、权重为 w((v,z)) 的边,先走到 v 的最短路再接这条边,可能改进到 z 的当前已知最短路。因此检查 d_z>d_v+w((v,z));若成立,就将 d_z 更新为 d_v+w((v,z))。

课件 p118 的 Question / Answer;下方 Proof 框说明为何其他边不必在这一步检查。

本节符号速查

5 个记号
v / u / z
v 本轮刚定案;u 假设为旧 S 中倒数第二个顶点;z 是要更新的目标。
P / P′
P 是假设新出现的候选路径;P′ 是旧 S 中已存在的 s→u 最短路径。
d_old[z] / d_new[z]
加入 v 前、加入 v 后到 z 的暂定距离。
w(v,z)
有向边 v→z 的非负边权。
relax
松弛操作:把旧 d[z] 与 d[v]+w(v,z) 比较,取较小者。

本节大写 P、P′ 指路径;下一节增广堆的 P[i] 是另一种对象。

松弛:旧路径与经过 v 的新候选比较

看 d[z] 从 10 降到 7,同时追踪路径前驱。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:v 定案后如何更新候选距离?对每条 v→z,做 relax:d[z]←min(d[z],d[v]+w(v,z))。d[v] 是起点到 v 的已证最短距离,w 是这条边权;如 d[v]=3、边权 4、原 d[z]=10,新 d[z]=min(10,3+4)=7,说明发现了一条更短的已知路径。若旧值 6,则仍保留 6。

为何只看 v 的出边?在加入 v 前已考虑过所有只用旧 S 作内部顶点的路径。若一条新有效候选 s→…→v→…→u→z 的末边来自早已在 S 的 u,那么到 u 的已证最短路径不需要等到 v 加入;把它接上 u→z 的候选在之前就已可用,不会产生新的更小值。因此真正因本轮新出现的改进可以由最后一条 v→z 发现。

Dijkstra 更新:为何只松弛 v 的出边

2-greedy.pdf · p118–121
Claim / Lemma

把 v 加入 S 后,若某个 d[z] 严格下降,则新最短候选路径的倒数第二个顶点必须是 v;因此只需检查 v→z。

Proof
  1. 假设有别的末边

    假设新出现的更短候选路径 P 末边是 u→z,且 u≠v。因为它在加入 v 后才出现,P 必经过 v,并可写成 s→…→v→…→u→z;u 已在旧 S。

  2. 利用 u 早已定案

    u 在 v 之前已定案,所以存在一条旧的 s→u 最短路径 P′,其内部不需经过 v,且长度不大于 P 的 s→u 前缀。旧 S 已允许 P′,接上 u→z 后早就是 d_old[z] 的候选。

    w(P′) ≤ w(P[s→u])。
    d_old[z] ≤ w(P′)+w(u,z) ≤ w(P)。
  3. 与“严格改进”矛盾

    P 的长度不小于旧 d[z],不能让 d[z] 严格下降。因此新改进只能由末边 v→z 提供;逐条做 d[z]←min(d[z],d[v]+w(v,z)) 即可。

    d_new[z] = min(d_old[z], d[v]+w(v,z))。

这补出了课件 p119–121 中“旧候选早已存在,所以不会带来新改进”的不等式。

Module

19 · Dijkstra 的数据结构:数组与增广堆

算法 / 主题:Dijkstra
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

Dijkstra 数组实现 · 课件问题

2-greedy.pdf · p123
Original English · Attempt 1 / Question

Store the dᵢ values in an array d[1..n]. At each stage: Perform a linear search of array d, ignoring those vertices already in S, and select the vertex v with smallest d[v] to be added to S. For each outgoing edge from vertex v to some z ∈ V∖S, update d[z] if necessary. Question: What is the time complexity of this algorithm?

中文翻译

把 dᵢ 存在数组 d[1..n]。每一步:线性扫描数组 d,跳过已在 S 中的顶点,选取 d[v] 最小的顶点 v 加入 S;再对 v 指向 S 外顶点 z 的每条出边,按需更新 d[z]。 问题:这一实现的时间复杂度是多少?

课件 p123 的 Attempt 1 与 Question;答案 O(n²+m)=O(n²) 在本节正文推导。

Dijkstra 堆实现 · 课件问题

2-greedy.pdf · p124
Original English · Question

How can we improve on this? The first operation isn’t a pure ‘find minimum’ because we have to skip over vertices already in S. Instead, when we add a vertex v to S, we could try deleting d_v from the data structure altogether. We now have three operations to support: find minimum, delete minimum, and update any.

中文翻译

怎样改进数组实现?第一个操作不只是“找最小值”,因为必须跳过已进入 S 的顶点。可以在顶点 v 加入 S 时直接把 d_v 从数据结构中删除。这样需要支持三种操作:找最小值、删除最小值、更新任意指定顶点的键值。

课件 p124 的改进问题;增广堆的 P 位置表用于实现“更新任意项”。

本节符号速查

6 个记号
n=|V| / m=|E|
n 是顶点数,m 是边数。
d[i]
源点到顶点 i 的暂定距离。
A[j]
增广最小堆数组第 j 项,内容是某个顶点编号和它的 d 值。
P[i]
顶点 i 在堆数组 A 中的当前位置,满足 A[P[i]] 对应 i。
S
已定案集合;进入 S 的顶点从堆中删除。
Decrease-Key
当 d[i] 变小,修改 A[P[i]] 的键值并向上调整堆。

P[i] 是定位堆项的数组,不是上一节证明中名为 P 的路径。

增广堆:Decrease-Key 与 P 位置表

在 A 堆数组交换元素时同步更新 P,才能保持快速定位。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:同一贪心算法为什么会有不同时间复杂度?n=|V|、m=|E|。若 d 放数组,每轮扫描 n 个位置找未定案最小值,共 n 轮 O(n²);所有出边合计松弛 O(m),总 O(n²+m),简单图 m=O(n²) 时写成 O(n²)。稀疏图中反复全表扫描浪费较多。

课件用增广最小堆:堆数组 A[j]=(顶点 i,d[i]),位置数组 P[i]=j,二者保持 A[P[i]] 就是 i 的堆项。最小堆取最小并删除 O(log n);松弛导致 d[i] 下降时,从 P[i] 直接找到它并上浮 O(log n)。堆交换两项时必须同步更新对应的 P,否则下一次 decrease-key 会改错位置。

建堆按课件保守计 O(n log n),n 次取最小和至多 m 次成功或尝试松弛各 O(log n),总 O((n+m)log n)。课件假定 s 可达全图,m≥n−1,可写 O(m log n)。例如 n=5、m=6,数量级由约 11 次对数操作主导;若改用数组则有约 25 次扫描检查,常数与具体实现另算。

Module

20 · MST:最轻跨割边为何安全

算法 / 主题:最小生成树
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

最小生成树 · 课件定义

2-greedy.pdf · p131
Original English · Definition

G = (V, E) is a connected graph and each edge e in E has a non-negative length. A spanning tree T of G is any tree which is a subgraph of G on the same vertex set V. The weight of a tree T is the sum of all edge lengths in T. A minimum spanning tree T of a connected graph G is a spanning tree of G with the smallest weight.

中文翻译

G=(V,E) 是连通图,且每条边 e∈E 有非负长度。G 的生成树 T 是与 G 有相同顶点集的树形子图。树 T 的权重是其所有边长之和。最小生成树(MST)是权重总和最小的生成树。

课件 p131 用 Definition 提出优化对象,没有单列 Problem 框;下方是同页割引理的正式证明。

本节符号速查

5 个记号
G=(V,E)
连通无向带权图,V 为顶点集,E 为边集。
S / V∖S
把顶点分成 S 与其补集 V∖S;这两侧构成一个割。
e / f
e 是割上唯一最轻边;f 是假设的 MST 路径中另一条跨割边。
T / T′
T 是假设漏掉 e 的最小生成树;T′ 是删 f 加 e 后的新生成树。
w(e)
边 e 的权重;整棵树的 w(T) 是其所有边权之和。

本节 S 表示割的一侧;Dijkstra 中 S 表示已定案集合。

MST 割交换:加入轻边、删除重边

给假设的 MST 加 e 形成环,再换出较重跨割边 f。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:在连通无向带权图中,怎样选权重和最小的生成树?生成树覆盖全部顶点、无环,恰有 n−1 条边;权重是所选边权之和。设非空真子集 S 与补集 V\S 构成一个割。若跨割边 e 是唯一最轻的,则课件引理说 e 属于每一棵 MST。

反证:若某 MST T 没有 e,把 e 加进 T 会形成唯一环;环上从 e 的 S 端走到 V\S 端的原树路径,必有一条别的跨割边 f。删除 f 后又成生成树;因 w(e)<w(f),新树更轻,矛盾。例跨割可选边权 3 与 5,若最优树用 5 而没用 3,可交换节省 2。

MST 割引理:唯一最轻跨割边必选

2-greedy.pdf · p131–132
Claim / Lemma

若连通无向图所有边权互异,S 是非空真子集,e 是 S 与 V∖S 之间唯一最轻边,则 e 属于每一棵最小生成树。

Proof
  1. 反设最优树漏选 e

    假设存在一棵 MST T 不含 e={u,v},其中 u∈S、v∉S。T 中 u 到 v 有唯一路径;这条路径必至少一次跨越该割,取路径上一条跨割边 f。

  2. 用轻边换重边

    把 e 加入 T 出现一个环,删掉该环上的 f 后仍连通且无环。由于边权互异且 e 是唯一最轻跨割边,w(e)<w(f)。

    T′ = T − {f} + {e}。
    w(T′) = w(T) − w(f) + w(e) < w(T)。
  3. 得到矛盾

    T′ 是更轻的生成树,与 T 最小矛盾。因此所有 MST 都必须含 e。

若跨割最轻边并列,只能保证存在一棵 MST 含指定的 e;“每一棵”需要课件给出的互异权重前提。

Module

21 · Kruskal:从森林中只加不成环的边

算法 / 主题:最小生成树
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

Prim · 课件算法原文

2-greedy.pdf · p133
Original English · Algorithm statement

Prim’s algorithm uses one large component, adding one of the isolated vertices to it at each stage. This algorithm is very similar to Dijkstra’s algorithm, but adds the vertex closest to S rather than the one closest to the starting vertex v.

中文翻译

Prim 算法维持一个不断扩大的主连通分量,每一步把一个尚未加入的顶点接入。它在形式上类似 Dijkstra,但比较的是顶点到当前集合 S 的距离,而不是到起点 v 的路径距离。

课件 p133 仅概述 Prim,本节演示是按该概述自编,不把它说成课件的完整 Prim 伪代码。

Kruskal · 课件算法原文

2-greedy.pdf · p133
Original English · Algorithm

Sort the edges E in increasing order by weight. An edge e is added if its inclusion does not introduce a cycle in the graph constructed thus far, or discarded otherwise. The process terminates when the forest is connected, i.e., when n−1 edges have been added.

中文翻译

将边集 E 按权重从小到大排序。依次考虑边 e:如果加入它不会使当前图产生环,就将它加入;否则舍弃。当森林变得连通,即已加入 n−1 条边时停止。

课件 p133 的 Kruskal’s Algorithm;优化目标沿用 p131 的 MST 定义。

本节符号速查

5 个记号
F
Kruskal 当前已经选出的无环边集合,即森林。
S
当前森林 F 中包含顶点 u 的那个连通分量,用作割的一侧。
e={u,v}
当前考虑的无向边,端点是 u 和 v;花括号不规定方向。
n−1
含 n 个顶点的生成树必须有的边数。
w(e)
边 e 的权重;Kruskal 按此数值从小到大检查边。

Prim 与 Kruskal 解决同一个 MST 问题;F 是选出的森林,不是函数名。

课件对 Prim 只给出概览:它与 Kruskal 都在逐步建森林,但 Prim 始终维持一个主分量,每次把离当前主分量最近的外部点连进来;下面先用自编图看这个动作,再看课件详讲的 Kruskal。

Prim 概览:只扩展一个连通主分量

课件只作概览;用同一张四点图和 Kruskal 对照它的选边顺序。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

Kruskal:选边、判环与分量合并

自编四点无向图。绿色是已选边,红色是当前因成环而跳过的边。

可单步、回退、重置;自编实例帮助观察状态,不能代替一般正确性证明。

这个部分回答什么问题:怎样把割引理变成可执行的算法?将所有边按权重升序排序,从 n 个独立顶点开始,依次检查边 (u,v):若 u、v 已在同一连通分量,加入会形成环,跳过;否则加入并合并两个分量。选到 n−1 条边时得到生成树。Prim 也用贪心,但维持一个不断扩大的主分量;本页聚焦课件详讲的 Kruskal。

安全性:设当前森林 F 中 u 所在分量为 S。被选边 e 跨越 S 与外部;任何比 e 更轻的跨割边若存在,先前已被处理,而且当时也会连接不同分量,不能被跳过。因此 e 是当前割的最轻边。若全图边权互异,它必在每一棵 MST;逐条选完得到唯一 MST。有同权时改用“存在某棵与已选森林兼容的 MST”作不变式。

Kruskal:用割引理证明每条入选边安全

2-greedy.pdf · p133–134
Claim / Lemma

边权互异时,Kruskal 产生唯一的 MST;课件 p134 的正式证明只覆盖互异权重情形。

Proof
  1. 选定一步和一个割

    设当前森林为 F,Kruskal 选入 e={u,v}。令 S 为 F 中 u 所在的整棵连通分量;v∉S,所以 e 跨越割 (S,V∖S)。

  2. e 是这道割的最轻边

    若有更轻的跨割边 f,它必在 e 之前被检查。f 两端在当前 F 中仍属于不同分量,因此在更早的森林里也不同;当时不可能因成环而被跳过,应已加入 F,矛盾。

    w(f)<w(e) 且 f 跨 (S,V∖S) ⇒ f 先被选入 ⇒ 其两端现应连通,矛盾。
  3. 调用割引理并收尾

    因此 e 是唯一最轻跨割边,属于每一棵 MST。对每条选边重复,得到 F 始终被每一棵 MST 包含。算法只加不成环的边,直到 n−1 条边连通全部顶点;它本身就是生成树,故等于唯一 MST。

边权相等时 Kruskal 仍能得到某棵 MST,但不能用“每一棵 MST 都含本边”作为不变式;现有正文另给并列权重的准确表述。

Module

22 · Union-Find:根代表连通分量

算法 / 主题:并查集
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

Union-Find · 课件操作原文

2-greedy.pdf · p137
Original English · Operations

Union(a, b) merges the set A containing a and the set B containing b into a single set A∪B. Find(a) returns the representative of the set containing a. Find(a) = Find(b) if and only if a and b are in the same set. Find(a) can change over time, as a result of Union operations.

中文翻译

Union(a,b) 把包含 a 的集合 A 与包含 b 的集合 B 合并为 A∪B。Find(a) 返回 a 所在集合的代表元。Find(a)=Find(b) 当且仅当 a、b 在同一个集合中;经过 Union,某个集合的代表元可能改变。

课件 p137 定义的是 Kruskal 所需的数据结构操作,并非新的独立优化题。

本节符号速查

5 个记号
A / B
包含元素 a、b 的两个当前不相交集合。
Find(a)
沿 parent 指针找出 a 所在集合的代表元(根)。
Union(a,b)
把 a、b 所在的两棵树合成一个集合。
parent[v]
顶点 v 的父顶点;若 v 是根,可让它指向自己。
rₐ / r_b
a、b 各自的根;只有 rₐ≠r_b 时才真正合并。

代表元的名字可能随 Union 改变;判断两点是否连通只比较两次 Find 的返回值。

并查集:Find、Union 与成环判断

父指针最终到同一根,就说明两端已在同一分量。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:如何快速判断一条 Kruskal 候选边是否成环?并查集 Union-Find 将每个当前连通分量表示为一棵有根树,parent 数组存父结点;根的 parent 指向自身或记特殊标记。Find(a) 沿 parent 到根,返回代表元;Find(a)=Find(b) 当且仅当两点已连通。Union(a,b) 先找两根,相同则不动,不同则让一个根指向另一个根。

操作本身:MakeSet(v) 令 parent[v]=v;Find(v) 沿 parent[v]、parent[parent[v]]……走到根;Union(a,b) 先求 ra=Find(a)、rb=Find(b),若 ra≠rb 才把一个根挂到另一个根。Kruskal 判断 (a,b) 是否成环,正是检查 Find(a)=Find(b);根的名字无意义,分组关系才重要。

例当前分量 {a,b} 与 {c,d},若候选边 b→c,Find(b) 与 Find(c) 不同,加入边并 Union;此后 b、c 代表元相同。若再看 a→d,两端根已相同,说明森林中已有一条 a 到 d 的路,再加边就形成环。Find 返回的具体顶点会随 Union 变化,代码只比较是否相等。

若合并时总随意把一棵树挂到另一棵树根下,树高最坏可接近 n;一次 Find、Union 就可能到 O(n)。下一节的按大小合并解决这个高度问题。

Module

23 · 按大小合并:为什么树高至多 log₂ n

算法 / 主题:并查集
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

按大小合并 · 课件算法原文

2-greedy.pdf · p143
Original English · Algorithm

Process Union(a, b) as follows. Run Find(a) and Find(b) to identify the roots of each tree, say c and d respectively. If c = d, then do nothing. Otherwise, place an edge between c and d: if subtree(c) ≥ subtree(d), then set parent(d) = c; if subtree(d) > subtree(c), then set parent(c) = d.

中文翻译

Union(a,b) 的处理方式如下:先调用 Find(a) 与 Find(b) 找出各自的根 c、d。若 c=d,则不做任何事。否则在 c、d 两根之间连一条父指针:若 subtree(c)≥subtree(d),令 parent(d)=c;若 subtree(d)>subtree(c),令 parent(c)=d。

课件 p143 的 Union 规则;树高 O(log n) 的证明见下方正式 Proof 框。

本节符号速查

6 个记号
size[r] / subtree(v)
前者是实现中根 r 所在树的大小;后者是证明中以 v 为根的子树顶点数。
parent(v)
v 的父顶点;沿父链反复向上可找到根。
h
一棵并查集树的高度,即最长叶到根路径的边数。
n / m
n 是图的顶点数;m 是边数,分析 Kruskal 总时间时使用。
2ʰ
2 的 h 次方;父链每上一层子树至少翻倍,所以根至少有 2ʰ 个点。
log₂n
以 2 为底的 n 的对数;树高满足 h≤log₂n。

size 是实际维护的根规模;subtree 是分析任意节点父链时使用的概念大小。

按大小合并:看规模翻倍与父链深度

跟踪八个顶点的 parent、根 size 和点 8 的 Find 路径。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:不用课外的高级并查集优化,也能把 Kruskal 做到什么时间?给每个分量根维护 size,即该分量顶点数。合并两根 c、d 时,把较小分量的根挂到较大分量根下,再更新新根 size;大小相同任选一边。每次一个顶点的深度增加 1,它所在的旧分量至多占合并后新分量的一半;经过 h 次使它变深的合并,所在分量至少扩大到 2ʰ,不能超过 n,因此 h≤log₂n。

按大小合并的具体规则:仅根存有效 size;若 size[ra]<size[rb] 就交换两根,之后令 parent[rb]=ra、size[ra]+=size[rb]。一个顶点的父链深度只有在它处于被挂上的较小一侧时才会增加;此时它所在新分量规模至少翻倍,所以最多增加 ⌊log₂ n⌋ 次。此复杂度分析不需要路径压缩。

按大小合并:树高的倍增证明

2-greedy.pdf · p142–146
Claim / Lemma

Union 总把较小树的根挂到较大树的根下时,含 n 个顶点的任何并查集树高度 h 都满足 h≤log₂n。

Proof
  1. 建立父子边的不变量

    当根 v 挂到根 w 下时,原先 w 的树至少与 v 的树一样大;挂上后 w 的子树大小至少为 v 的两倍。v 不再是根,以后新树只会接到根上,所以 v 的子树大小不会增加,w 的只会增大。

    subtree(w) ≥ 2·subtree(v)(每条父子边)。
  2. 沿最长父链向上

    取一条有 h 条父指针的叶到根路径。每上升一层,子树大小至少翻倍;叶子的子树至少有 1 个点。

    subtree(leaf)≥1,subtree(parent(leaf))≥2,
    subtree(parent²(leaf))≥4,…,subtree(root)≥2ʰ。
  3. 用总顶点数封顶

    整棵树至多 n 个顶点,因此 2ʰ≤n,两边取以 2 为底的对数得 h≤log₂n。Find 沿父链走至多 O(log n),Union 调用 Find 后只改一条父指针,也为 O(log n)。

    2ʰ ≤ subtree(root) ≤ n  ⇒  h ≤ log₂n。

课件 p146 使用的是概念上的 subtree 大小;实现只存根的 size 仍可用同一倍增不变量分析。

Find/Union 每次 O(log n)。Kruskal 对 m 条边排序 O(m log m)=O(m log n)(简单图 m<n²);之后每条边最多做两次 Find,共 O(m log n),选 n−1 条边再 Union O(n log n)。连通图 m≥n−1,故总 O(m log n)。例 n=4、m=5,排序 5 条边后最多查 10 次端点根;不要把每次 Find 误算成 O(1)。

Module

24 · 最大间距聚类:Kruskal 在 k 个分量时停下

算法 / 主题:最大间距聚类
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

最大间距聚类 · 原题

2-greedy.pdf · p150
Original English · Problem

Instance: A complete graph G with weighted edges representing distances between the vertices, and an integer k. Task: Partition the vertices of G into k disjoint subsets so that the smallest distance between two points belonging to different sets of the partition is as large as possible.

中文翻译

输入:完整图 G,边权表示顶点两两之间的距离,并给定整数 k。 任务:把顶点分成 k 个互不相交的组,使不同组中的两点之间的最小距离尽可能大。

课件 p150 的完整 Problem;同页解法是 Kruskal 在剩下 k 个分量时提前停止。

本节符号速查

6 个记号
G / k
G 是完整的带权距离图;k 是最终要得到的分组个数。
w(u,v)
顶点 u、v 之间的边权或距离。
spacing
分属不同组的顶点对中,最小的一条跨组边权。
δ
希腊字母 delta,表示贪心输出分组的 spacing。
x / y
贪心把它们放在同组、但另一种分组把它们分开的两点。
{z,w}
另一方案的组边界上被路径跨过的一条边;这里的第二个 w 是顶点名称。

在 w(z,w) 中,第一个 w 是“取边权”的函数名,括号内第二个 w 是顶点;同形字母扮演不同角色。

最大间距聚类:Kruskal 停在 k 个分量

从四组到两组;停下后的最短跨组边就是 spacing。

绿色表示已选或本步重点,红色表示反设或较差选择。实例为自编演示;一般正确性见相邻证明。

这个部分回答什么问题:给完整的两两距离图,把点分成 k 组,怎样最大化不同组之间的最小距离?令 spacing(分组)=min{w(u,v):u、v 在不同组},假定 2≤k≤n。按 Kruskal 升序加边,但在森林恰有 k 个连通分量时停止;这些分量就是输出的 k 组。

完整算法:把完整距离图所有边按权重排序,从 n 个单点分量开始逐条扫描;端点根不同才 Union 并让分量数减 1;一旦分量数等于 k 就停止并输出这些分量。下一条能连接不同分量的最轻边,其权重就是输出分组的 spacing。若 k=n,初始分组已完成,无需选边。

证明:设贪心分组间距为 δ。任意另一种不同的 k 分组,必有一对点 x、y 在贪心中同组,却被另一方案分开。贪心森林中 x 到 y 有路径;这条路径必跨过另一方案某个组的边界,其跨界边权至多 δ,因为贪心合并前用到的边权不超过停止时最小的跨分量边 δ。因此另一方案的间距 ≤δ。若两方案其实划分相同,目标自然相等。

最大间距聚类:路径跨界证明

2-greedy.pdf · p150–152
Claim / Lemma

在完整带权图上按 Kruskal 从小到大合并,恰好剩 k 个分量时停止,所得 k 组的间距 δ 不小于任意其他 k 分组的间距。

Proof
  1. 定义贪心间距

    令 δ 为停下后连接两个不同贪心分量的最轻边权。此前加入森林的每条边都按升序处理,故权重至多 δ。

    δ = min{w(u,v):u、v 位于不同贪心组}。
  2. 找两种分组不一致的点

    取不同于贪心分组的任意另一种 k 分组。若贪心每组都完全包含在另一组中,由于双方组数同为 k,两种分组会相同,矛盾。因此存在 x、y 在同一贪心组,却分属另一方案的不同组。

  3. 沿贪心树路径跨出另一方案的组

    同一贪心组是一棵树,x 到 y 有唯一路径 P。由于 x、y 在另一方案不同组,P 必有某条边 {z,w} 跨过另一方案的组边界;它已被贪心选过,故 w(z,w)≤δ。

    spacing(另一方案) ≤ w(z,w) ≤ δ。
  4. 得出最优性

    任意另一种 k 分组的 spacing 都不超过 δ;若分组相同则相等,所以贪心最大化间距。

课件 p151–152 的证明就是“不同分组 ⇒ 某条已选路径穿过其边界”;公式把跨界边与 spacing 明确连接起来。

完整图有 m=Θ(n²) 条边;排序 O(m log m)=O(n² log n),并查集扫描不超过此量。只维护已有的稀疏边集合会改变题目输入和可比较的跨组距离,不能直接照搬完整距离图的结论。

Module

25 · 通用方法、边界与术语回看

算法 / 主题:综合方法
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

这个部分回答什么问题:遇到一题新的贪心或图题,应该先识别哪种证明形状?排序题比较相邻交换的目标差;合并题把总代价写成叶权重×深度;图上选择题先缩出 SCC/DAG 或找到割;最短路题用第一条离开已定案集合的边。这些线索只指向可尝试的方法,具体规则仍需证明。

看见的结构候选方法必须验证的安全性
排列改变等待或延误相邻逆序交换交换保持可行且期望/最大延误不升
重复合并、码树最小两项合并最轻两叶可成为最深兄弟并缩并
互相可达、传播SCC→凝聚 DAG→零入度源 SCC 必选,源 SCC 又能到达全图
非负权单源路径Dijkstra 取最小暂定距离任意更短路径首次离开 S 时必已不可能更短
连通无向边权和最轻跨割边/Kruskal交换边后仍是树且不更重
最大间距 k 聚类Kruskal 停在 k 分量任意别的分组有跨界边不重于当前间距
  • 先写明目标:平均读取时间、最大有符号延误、平均码长、传感器数量、路径长度、树总权重和间距不是同一量。
  • 把前提列在算法旁:非负边权、固定单源、无向连通图、完整距离图、正长度文件等。
  • 把正确性拆为合法性、局部选择的安全性、重复后的终止/最优性;复杂度另算。
  • 若找到合法反例,只能否定这一条贪心规则及其声称的适用范围;证明不出来也不等于已经证明不存在任何贪心法。
English中文回想
adjacent inversion / exchange argument相邻逆序 / 交换论证
prefix code / Huffman code前缀码 / 最优平均长度编码
SCC / condensation graph强连通分量 / 缩点后的凝聚图
topological order / indegree拓扑序 / 入度
relaxation / decrease-key松弛 / 减小堆键值
cut / minimum spanning tree割 / 最小生成树
Union-Find / union by size并查集 / 按大小合并
maximum-spacing clustering最大间距聚类
Module

26 · 自测:先写自己的证明,再展开答案

算法 / 主题:证明方法
✎ 我的笔记未填写

输入时自动保存到当前浏览器。

本节 PPT 来源 · PDF 实际页码

依用户要求编入 Week03;原文件位于 week2 文件夹,正式第三周课堂范围未单独核实。自编数值和图示已在正文标明。

每题先判断目标、前提与关键不等式,写下理由后再展开答案。答案中的数字例子若标为自编,仅供练习,不作为课堂原题。

1. 等概率磁带长度 3、1、2,应如何排序?为什么只比较相邻两项就够?

查看答案与推理

排成 1、2、3。若最优排列有相邻逆序 Lᵢ>Lᵢ₊₁,交换使缩放后的期望 nE 降低 Lᵢ−Lᵢ₊₁>0,矛盾;没有相邻逆序即整体已排序。

2. 磁带题用相邻交换证明短文件先放,为什么实际代码仍建议用 mergesort?

查看答案与推理

相邻交换是为了证明每个长度逆序都能被消除而不变差,并未要求把交换当作实现。真正执行排序可用 O(n log n) 的归并排序:递归拆分,再线性合并有序子列;逐个交换逆序的冒泡排序最坏 O(n²)。

3. 文件 A 长 2、概率 0.2,B 长 4、概率 0.8。A 与 B 谁在前?算出两个顺序的期望。

查看答案与推理

p/L 分别 0.1、0.2,所以 B 在前。B→A:0.8×4+0.2×6=4.4;A→B:0.2×2+0.8×6=5.2。

4. 最大延误题中,交换相邻截止期逆序后,哪两个任务的延误会变化?为什么最大值不升?

查看答案与推理

只有被交换的两项变化,后续任务总完成时刻不变。先做较早截止期的任务使它提前;后做较晚截止期的任务虽然被推迟,但其新完成时刻等于原先较早截止期任务的完成时刻,因此其新延误不超过那项原延误。

5. 2、3、7、8 四个数组最终长度都为 20,为什么合并顺序仍重要?

查看答案与推理

目标是每一步的搬动成本总和,不是最终长度。最短先合的成本 5+12+20=37;最长先合的成本 15+18+20=53。先合的项会在后续重复计费。

6. 为什么 cake 与 cats 可以编码为同一位串?前缀码怎样避免?

查看答案与推理

课件码字中 t=11 是 k=111 的前缀;10101011100 可解成 101|010|111|00 或 101|010|11|100。前缀码把符号都放树叶,读到一个叶便唯一确定符号。

7. Huffman 例中第一次合并了哪两个权重?最终平均码长是多少?

查看答案与推理

最小的是 e=.05 和 d=.18,合成 de=.23。课件给的一组码长为 2、2、2、3、3,概率加权平均为 2.23 位/符号。

8. 从 e 在原图能到 d,e,f,g,h;在反图能到 a,b,c,d,e,f。e 的 SCC 是什么?

查看答案与推理

取交集,Cₑ={d,e,f}。只用任一单向可达集合都不足以判定强连通。

9. 有向图 A↔B、B→C。Tarjan 为什么先弹出 {C},再弹出 {A,B}?

查看答案与推理

假设 DFS 从 A→B→C。C 没有回到栈内更早顶点的边,low[C]=id[C],所以先弹出 {C}。B→A 指向仍在栈中的 A,使 low[B]=id[A],向上返回后 A 与 B 一起弹出。B 能到 C,但 C 回不到 B,因此不在同一 SCC。

10. Kosaraju 在同一有向图 A↔B、B→C 中,为什么第二轮要在反图按第一轮完成时间从晚到早搜索?会得到哪两组?

查看答案与推理

第一轮原图 DFS 从 A 开始,完成顺序 C、B、A,逆序是 A、B、C。反图从 A 只能走到 B,得 {A,B};剩下 C 单独一组。按这个顺序处理可避免反向跨分量边把尚未处理的另一组一起带入;两轮 DFS 与建反图总共 O(V+E)。

11. 为什么凝聚图每个零入度 SCC 至少要一座传感器?为什么这些传感器又足够?

查看答案与推理

零入度 SCC 不会被别的分量激活,所以各需一个。任意分量在有限 DAG 中沿入边倒走终会到某个零入度分量,因此可从该源分量顺边激活,覆盖所有分量。

12. Kahn 算法队列空了但还有顶点时说明什么?

查看答案与推理

剩余图中每个点仍有入边,因此存在有向环,不可能输出覆盖全部顶点的拓扑序。

13. Dijkstra 为何要求非负边权?一条尚未考虑的路径首次离开 S 于 y,如何比较它与当前选中的 v?

查看答案与推理

到 y 的前缀至少 d[y],非负边使整条路径至少 d[y],而贪心取最小保证 d[v]≤d[y];所以它不能比 d[v] 更短。负边会破坏“整条路径不短于前缀”。

14. 一条边 v→z 权重 4,d[v]=3、d[z]=10;松弛后是多少?

查看答案与推理

d[z]=min(10,3+4)=7。它是目前已知的候选距离,直到 z 被取出加入 S 才定案。

15. 增广堆的 P[i] 用来做什么?每次堆交换需要同步修改什么?

查看答案与推理

P[i] 记录顶点 i 在堆数组 A 中的位置,供 decrease-key 直接定位。堆项交换时必须同步更新两个顶点的 P,否则后续键值更新会定位错误。

16. 割上最轻边存在并列时,能否说它属于每一棵 MST?

查看答案与推理

不能。并列最轻只保证存在某棵 MST 可以选这条边;若它是严格唯一最轻,交换论证才推出它属于每棵 MST。

17. Prim 与 Kruskal 在四点图 AB=1、CD=2、AC=3、BC=5、BD=6、AD=8 上,起点 A 时各先选哪条边?最后总权重是多少?

查看答案与推理

Prim 先从当前树 {A} 跨出去选 AB(1),再从 {A,B} 跨出去选 AC(3),最后选 CD(2);Kruskal 按全图权重先看 AB(1)、CD(2)、AC(3),三条均不成环。两者都得到权重 1+2+3=6 的 MST,但查看候选边的方式和顺序不同。

18. Kruskal 中 Find(u)=Find(v) 时为什么要跳过边 (u,v)?

查看答案与推理

当前森林已有 u 到 v 的路径;再加这条边会形成环,无法属于正在构造的森林。

19. 按大小合并的并查集中,n=16 时一个点的深度最多能增加多少次?

查看答案与推理

最多 log₂16=4 次。每次深度增加,它所在分量至少翻倍,从 1 至多到 16。

20. 最大间距聚类中 k=2、点为 0、1、5、6,部分 Kruskal 输出什么?间距是多少?

查看答案与推理

输出 {0,1} 与 {5,6},跨组最近的是 1 与 5,距离 4。注意目标是跨组最小距离,不是组内边权总和。