离散数学 1 第 7 章:关系的运算——复合、闭包与沃舍尔算法

写于 2026-11-01

这一章把第 6 章"缺哪条边"的观察变成算法。复合、逆、幂是三种基本运算,三种闭包是"给关系补性质"的标准操作,沃舍尔算法则是把传递闭包从 O(n⁴) 压到 O(n³) 的那一步。学这一章最容易出错的不是算法本身,而是复合的顺序:先把"谁先作用"钉死,再谈矩阵乘法怎么写,否则布尔积乘反了,后面闭包全错。

一、复合运算

设 R⊆A×B,S⊆B×C,则 R 与 S 的复合

R∘S = { | 存在 y∈B,使 ∈R 且 ∈S} ⊆ A×C

读法是:先走 R,再走 S。这里必须提醒一句:不同教材对 R∘S 的书写顺序约定相反,有的写成 S∘R 表示先 R 后 S。做题时先看题目给的定义式,不要凭记忆套。本文统一采用上式,即 ∈R∘S 意味着 x 经 R 到某个 y、再经 S 到 z。

矩阵写法:设 M_R 是 m×n 布尔矩阵、M_S 是 n×p 布尔矩阵,则

(M_{R∘S})[i][j] = ∨_{k=1..n} ( M_R[i][k] ∧ M_S[k][j] )

这就是布尔积,与线性代数的矩阵乘法同形,只是把"乘"换成 ∧、把"加"换成 ∨。写代码时最容易错的是下标顺序:布尔积不满足交换律,M_R⊙M_S 与 M_S⊙M_R 一般不同(连形状都可能不匹配)。

手工算一个:A = {1,2,3},R = {<1,2>, <2,3>},S = {<2,1>, <3,3>}。找 x 经 R 到 y、再经 S 到 z:x=1 时 y=2,S 从 2 只能到 1,得 <1,1>;x=2 时 y=3,S 从 3 到 3,得 <2,3>。所以 R∘S = {<1,1>, <2,3>}。x=3 在 R 里没有出边,自然不产生结果——复合不会凭空造出信息,结果必然落在 A×C 之内。

图上的解释最直观:R∘S 中的边 ,对应图中一条 x→y→z 的长度为 2 的通路。

复合的代数性质:

  • 结合律成立:(R∘S)∘T = R∘(S∘T)。
  • 交换律不成立,一般 R∘S ≠ S∘R。
  • 恒等关系是单位元:I_A∘R = R∘I_B = R。
  • 对并双向分配:R∘(S∪T) = (R∘S)∪(R∘T)。
  • 对交只有单向:R∘(S∩T) ⊆ (R∘S)∩(R∘T),反向不成立。

二、逆关系与幂运算

逆关系 R⁻¹ = { | ∈R} ⊆ B×A。矩阵上就是转置,图上就是所有边反向(自环不变)。

性质:(R⁻¹)⁻¹ = R;(R∘S)⁻¹ = S⁻¹∘R⁻¹(顺序必须反转,与穿脱外套同序);(R∪S)⁻¹ = R⁻¹∪S⁻¹;(R∩S)⁻¹ = R⁻¹∩S⁻¹。还有一条判定:R 对称当且仅当 R = R⁻¹。

幂运算递归定义:R⁰ = I_A,R^{n+1} = Rⁿ∘R。于是 R¹=R、R²=R∘R、R³=R²∘R。

  • 指数相加:R^m∘R^n = R^{m+n};指数相乘:(R^m)^n = R^{mn}。
  • 矩阵上是布尔幂:M_{R^n} = (M_R)^n。
  • 图上:∈Rⁿ 当且仅当存在从 x 到 y 的长度为 n 的通路。

这条图解释是后面求闭包的钥匙:传递闭包要的正是"任意长度 ≥1 的通路",于是

t(R) = R ∪ R² ∪ R³ ∪ … ∪ Rⁿ(|A| = n)

为什么到 n 就够?因为任何长度超过 n 的通路必然重复经过某个结点,把重复段剪掉,能得到一条更短的通路,所以长度 ≥ n 的可达性都已被前 n 次幂覆盖。换个角度也能看出来:A 上只有 2^(n²) 个不同的关系,幂序列 R⁰、R¹、R²、… 必然会重复,不会无限产生新关系。

三、三种闭包

闭包的定义统一为:包含 R 的、具有性质 P 的最小关系("最小"按集合包含 ⊆ 理解)。存在性与唯一性由这个"最小"保证。

闭包 定义式 矩阵操作 图操作
自反闭包 r(R) R ∪ I_A 主对角线全部置 1 每个结点加一个自环
对称闭包 s(R) R ∪ R⁻¹ M ∨ Mᵀ 每条边加一条反向边
传递闭包 t(R) R ∪ R² ∪ … ∪ Rⁿ M ∨ M² ∨ … ∨ Mⁿ 所有长度 ≥2 的通路补捷径边

三者都不改变原有边,只增不减,这从定义式一眼可见。注意 r(R)、s(R) 可以一步写出,t(R) 不行——直接用幂并集要算 n 次布尔积,代价 O(n⁴),这就是需要沃舍尔算法的原因。

闭包的定义里还有一条常被忽略的要求:最小性。要证明某个关系 C 就是 r(R),必须证两件事——C 自反且包含 R;任何包含 R 的自反关系都包含 C。第二句才是"最小"的实质,只写第一句要丢一半分。

三个算子的次序也值得说清:r 与 s 可交换,r(s(R)) = s(r(R));但只要 t 参与,次序就影响结果。取 R = {<1,2>},t(s(R)) 补出自环,得到 {<1,2>,<2,1>,<1,1>,<2,2>};而 s(t(R)) 只有 {<1,2>,<2,1>}。要一次性得到同时满足自反、对称、传递的关系,按 r→s→t 逐层加厚即可。

四、沃舍尔算法

思路是逐步放开中间结点:第 k 轮只允许路径经过编号 ≤ k 的结点作为中间点,把新接通的可达关系写进矩阵。

// M 为 n×n 布尔矩阵,初始为 R 的关系矩阵
for (int k = 1; k <= n; k++)
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            M[i][j] = M[i][j] || (M[i][k] && M[k][j]);

不变式:第 k 轮结束后,M[i][j] = 1 当且仅当存在一条从 i 到 j、且中间结点全部取自 {1,…,k} 的通路。k 走到 n 时,"中间结点"不再受限,矩阵就是传递闭包。循环变量 k 必须放最外层,这是算法正确性的关键,交换顺序就会算错。

手工演示:A = {1,2,3,4},R = {<1,2>, <2,3>, <3,4>}。

轮次 k 新增的 1 原因
k=1 无 第 1 列全 0,结点 1 没有入边
k=2 M[1][3] 借 2 接通 1→2→3
k=3 M[1][4]、M[2][4] 借 3 接通 1→3→4、2→3→4
k=4 无 结点 4 没有出边

最终 t(R) = {<1,2>,<1,3>,<1,4>,<2,3>,<2,4>,<3,4>}。可以看到第 3 轮一次性补了两条,因为第 2 轮已经把 1→3 接通,这一轮才能顺着用——按 k 递增的顺序推进,前面补的边会被后面轮次继续利用,这正是算法只需 O(n³) 的原因。手算时建议每轮把矩阵抄一遍并标出新增的 1,出错时能立刻定位是哪一轮接错了路径。

复杂度:时间 O(n³),空间 O(n²) 且可原地。作为对比,幂并集法要算 n 次布尔积,是 O(n⁴)。沃舍尔算法与求最短路的 Floyd 算法结构完全同构,只是把 min/+ 换成 ∨/∧。

方法 做法 复杂度 适用场景
幂并集 R∪R²∪…∪Rⁿ O(n⁴) 手算小规模、验算答案
沃舍尔 三重循环,原地更新矩阵 O(n³) 通用,代码实现首选
图搜索 从每个结点做一次 DFS/BFS O(n·(n+e)) 稀疏图、只需要可达性

易错点

  1. 复合顺序:R∘S 按本文约定是"先 R 后 S",换教材要先核对定义式;矩阵上是 M_R⊙M_S,不能写反。
  2. (R∘S)⁻¹ = S⁻¹∘R⁻¹,顺序必须反转,写成 R⁻¹∘S⁻¹ 是错的。
  3. t(R) 的幂并集里从 R¹ 开始,不含 R⁰ = I_A;若把 R⁰ 并进去,算出来的是自反传递闭包,多了一堆自环。
  4. 沃舍尔算法的 k 必须是最外层循环,写成 i 在最外层就退化成错误的松弛。
  5. 闭包只增边不减边;如果算出的闭包比原关系"少"了元素,一定是某步覆盖写错了。

这一章在整门课里的位置

本章的三种运算全部建立在第 5 章的关系矩阵与关系图上,判定依据则来自第 6 章的五条性质——闭包就是"按性质补边"。第 8 章的等价关系要求自反、对称、传递三条同时成立,等价类其实就是 r、s、t 依次作用后的连通块;而偏序的哈斯图,是把传递闭包里那些"多余"的边再删回去。

本文是《离散数学 1:数理逻辑与集合论》第 7 章的知识点摘要。完整板书与例题见 课程页;上一章 关系的性质,下一章 偏序关系。

相关课程

这篇笔记涉及的主题,我录过对应的视频课程: