传递闭包及其构造
定义:
有一天我在思考这样一个问题:我知道从图书馆到梅园是连通的,并且知道从图书馆到操场是连通的,可是我并不知道从梅园到操场的路线,所以在我的地图里,梅园和操场是连通的,但不是直接连通的,那么类似的,我应该如何查询两个不直接连通的点之间的可达性。
传递闭包其实就是这样一个问题,,对于一个关系R,我们可以构造一个关系S,满足以下条件:
- R⊆S
- S是传递的
- S是所有包含关系R的传递关系的子集
那么,我们称S是R的传递闭包。
传递闭包的构造
如果(x,y)∈R,那么有向图G上存在一条从x到y长度为1的有向边,于是我们得到了关系R的有向图表示。
那么有以下结论:
- 设R是A上的关系,从a到b有一条长度为n的路径,当且仅当(a,b)∈RnR^nRn
证明如下:
使用数学归纳法。
(1)n=1时,从a到b存在一条长为1的路径,当且仅当(a,b)∈R,结论为真。
(2)对于正整数n,结论为真。从a到b存在一条长度为n+1的路径,当且仅当存在一条从a到c的长度为1的路径并且存在一条从c到b的长度为n的路径,即存在c∈A,使得(a,c)∈R,(c,b)∈RnR^nRn,等价于(a,b)∈RnR^nRn。因此,从a到b存在一条长度为n+1的路径,当且仅当(a,b)∈Rn+1R^{n+1}Rn+1。结论得证。
我们可以证明,构造一个关系的传递闭包,等价于在有向图中确定顶点之间是否存在路径。
也就是说我们可以这样来构造关系R的传递闭包S:
SSS=∪k=1∞\cup_{k=1}^∞∪k=1∞RkR^kRk
证明如下:
(1)S是传递的,如果(a,b)∈S并且(b,c)∈S,那么也就是说有向图上存在从a到b的路径和从b到c的路径,那么必然存在从a到c的路径,也就是(a,c)∈S。
(2)对于任意的包含R的传递关系S0S_0S0,都有S⊆S0S_0S0。首先我们需要使用一个定理:如果集合R是传递的,那么RnR^nRn⊆RRR(n=1.2…)。我们稍后再证明其正确性。那么,因为S0S_0S0是包含R的传递关系,所以S0nS_0^nS0n⊆S0S_0S0(n=1,2…),那么对于S∗=∪k=1∞S0kS^*=\cup_{k=1}^∞S_0^kS∗=∪k=1∞S0k,S∗S^*S∗⊆S0S_0S0,因为R⊆S0S_0S0,所以有S=∪k=1∞RkS=\cup_{k=1}^∞R^kS=∪k=1∞Rk⊆S∗S^*S∗⊆S0S_0S0,又因为R⊆SSS,所以可证明对于S属于任意包含R的传递关系。
(3)综上可证明S为关系R的传递闭包。
下面我们证明上面的证明遇到的定理:如果集合R是传递的,那么RnR^nRn⊆RRR(n=1.2…)。
证明如下:
(1)使用数学归纳法证明。n=1时,定理显然成立。
(2)假设对于正整数n,定理成立,假设(a,b)∈Rn+1R^{n+1}Rn+1,因为Rn+1R^{n+1}Rn+1=RnR^{n}RnRRR,所以存在x∈A,满足(a,x)∈RnR^nRn,并且(x,b)∈RRR,又因为RnR^nRn⊆RRR,所以(a,x)∈RRR,因为RRR是传递的,所以(a,b)∈RRR,即可证明n+1时,定理成立。
(3)综上可证明对于n=1,2,…,如果集合R是传递的,那么RnR^nRn⊆RRR。
由鸽巢原理,我们可以获得,S=∪k=1∞Rk=∪k=1nRkS=\cup_{k=1}^∞R^k=\cup_{k=1}^nR^kS=∪k=1∞Rk=∪k=1nRk。(可以仿照n个点的有向图中如果两点之间存在路径,那么这两点之间一定存在一条长度不超过n的路径来证明。)
显然,这个最原始的求传递闭包的算法是O(n4)O(n^4)O(n4),Warshell算法对其进行了优化,把时间复杂度优化到了O(n3)O(n^3)O(n3)。
Warshell算法
我们使用一系列0-1矩阵W0W_0W0、W1W_1W1、…、WnW_nWn来储存有向图的信息,设有向图中的顶点为(1,2,…,n),定义WkW_kWk中w[i][j][k]=1w[i][j][k]=1w[i][j][k]=1代表从iii到jjj存在一条路径,这条边上的内部顶点(也就是这条路径上除去起点和终点以外的点)全部属于(1,2,…,k)。其中W0W_0W0是关系R的原始矩阵,WnW_nWn为关系R的传递闭包。
显然我们可以通过Wk−1W_{k-1}Wk−1来直接计算WkW_kWk,如果w[i][j][k]=1w[i][j][k]=1w[i][j][k]=1,只有以下两种情况:
(1)w[i][j][k−1]=1w[i][j][k-1]=1w[i][j][k−1]=1
(2)w[i][k][k−1]=1w[i][k][k-1]=1w[i][k][k−1]=1并且w[k][j][k−1]=1w[k][j][k-1]=1w[k][j][k−1]=1
于是我们可以得到Wk−1W_{k-1}Wk−1到WkW_kWk的转移方程:
w[i][j][k]=w[i][j][k−1]w[i][j][k]=w[i][j][k-1]w[i][j][k]=w[i][j][k−1]∪\cup∪(w[i][k][k−1](w[i][k][k-1](w[i][k][k−1]∩\cap∩w[k][j][k−1])w[k][j][k-1])w[k][j][k−1])
伪代码如下:
for k:=1 to n
for i:=1 to n
for j:= 1 to n
w[i][j]:=w[i][j]|(w[i][k]&w[k][j])
显然时间复杂度为O(n3)O(n^3)O(n3)。
共同学习,写下你的评论
评论加载中...
作者其他优质文章