算法导论23.2 Exercises 答案
23.2-1
每步的迭代结果如下:
\(\begin{aligned} &\begin{pmatrix} 0&\infty&\infty&\infty&-1&\infty\\ 1&0&\infty&2&\infty&\infty\\ \infty&2&0&\infty&\infty&-8\\ -4&\infty&\infty&0&3&\infty\\ \infty&7&\infty&\infty&0&\infty\\ \infty&5&10&\infty&\infty&0 \end{pmatrix} \underrightarrow{k=1} \begin{pmatrix} 0&\infty&\infty&\infty&-1&\infty\\ 1&0&\infty&2&0&\infty\\ \infty&2&0&\infty&\infty&-8\\ -4&\infty&\infty&0&-5&\infty\\ \infty&7&\infty&\infty&0&\infty\\ \infty&5&10&\infty&\infty&0 \end{pmatrix} \underrightarrow{k=2} \begin{pmatrix} 0&\infty&\infty&\infty&-1&\infty\\ 1&0&\infty&2&0&\infty\\ 3&2&0&4&2&-8\\ -4&\infty&\infty&0&-5&\infty\\ 8&7&\infty&9&0&\infty\\ 6&5&10&7&5&0 \end{pmatrix}\\ \underrightarrow{k=3} &\begin{pmatrix} 0&\infty&\infty&\infty&-1&\infty\\ 1&0&\infty&2&0&\infty\\ 3&2&0&4&2&-8\\ -4&\infty&\infty&0&-5&\infty\\ 8&7&\infty&9&0&\infty\\ 6&5&10&7&5&0 \end{pmatrix} \underrightarrow{k=4} \begin{pmatrix} 0&\infty&\infty&\infty&-1&\infty\\ -2&0&\infty&2&-3&\infty\\ 0&2&0&4&-1&-8\\ -4&\infty&\infty&0&-5&\infty\\ 5&7&\infty&9&0&\infty\\ 3&5&10&7&2&0 \end{pmatrix} \underrightarrow{k=5} \begin{pmatrix} 0&6&\infty&8&-1&\infty\\ -2&0&\infty&2&-3&\infty\\ 0&2&0&4&-1&-8\\ -4&2&\infty&0&-5&\infty\\ 5&7&\infty&9&0&\infty\\ 3&5&10&7&2&0 \end{pmatrix}\\ \underrightarrow{k=6} &\begin{pmatrix} 0&6&\infty&8&-1&\infty\\ -2&0&\infty&2&-3&\infty\\ -5&-3&0&-1&-6&-8\\ -4&2&\infty&0&-5&\infty\\ 5&7&\infty&9&0&\infty\\ 3&5&10&7&2&0 \end{pmatrix}\\ \end{aligned}\)
23.2-2
对于图\(G=(V,E)\)的邻接矩阵\(W\),我们设\(w_{ij}=1\)当且仅当边\((i,j)\in E\),此外,\(\forall i\in
V,w_{ii}=1\)。接下来参照子程序EXTEND-SHORTEST-PATHS
,构造出子程序EXTEND-PATHS'
。那么剩下的是调用这个子程序即可求出传递闭包,整个过程和23.1节一致,由TRANSITIVE-CLOSURE'
给出。
1 | EXTEND-PATHS'(T(r-1), W, T(r), n) |
23.2-3
按照方程23.7和23.8,修改后的算法为FLOYD-WARSHALL''
。
1 | FLOYD-WARSHALL''(W, n) |
首先证明\(G_{\pi,i}\)是一个有向无环图。当\(\pi_{ij}^{(k)}\)被更新成一个值\(l\)时,说明\(d_{ij}^{(k)}=d_{il}^{(k-1)}+w_{lj}\)。由于\(d_{ij}^{(k-1)}\)是\(d_{ij}^{(k)}\)的一个子问题选项,因此有\(d_{ij}^{(k)}\le d_{ij}^{(k-1)}\),从而得到\(d_{ij}^{(k)}\ge d_{il}^{(k-1)}+w_{lj}\)。接下来的证明和引理22.16的证明类似。假设\(G_{\pi,i}\)构成了一个环\(v_0,v_1,\dots,v_m\),其中\(v_0=v_m,\forall j\in[1,m],\pi^{(k)}_{i,v_j}=v_{j-1}\)都成立。那么在\(\pi_{i,v_m}\)更新成\(v_{m-1}\)前,都有:
\[d_{i,v_j}^{(k)}\ge d_{i,v_{j-1}}^{(k)}+w_{v_{j-1},v_j},j=1,2,\dots,m-1\]
由于\(\pi_{i,v_m}\)被更新,所以在\(\pi_{i,v_m}\)被更新成\(v_{m-1}\)前,有
\[d_{i,v_{m}}^{(k)}>d_{i,v_{m-1}}^{(k)}+w_{v_{m-1},v_m}\]
将这\(m\)条不等式左右各自相加,最终得到\(\displaystyle{\sum_{j=1}^m w(v_{j-1},v_j)}<0\)。这和图\(G\)没有负环是矛盾的。因此,\(G_{\pi,i}\)是一个有向无环图。
接下来和引理22.17的证明类似。\(G_{\pi,i}\)从\(i\)到每个节点\(u\)之间只存在唯一一条路径。如果存在两条路径\(p_1:i\rightsquigarrow u\rightsquigarrow x\rightarrow z\rightsquigarrow u,p_2:i\rightsquigarrow u\rightsquigarrow y\rightarrow z\rightsquigarrow u\),并且\(x\neq y\),那么说明\(\pi_{iz}=x,\pi_{iz}=y\)同时成立。这是不可能的,因此从\(i\)到每个节点\(u\)之间只存在唯一一条路径,\(G_{\pi,i}\)是以\(i\)为根形成的一棵树。
最终,由于算法正确地求解出了\(d_{ij}^{(n)}=\delta(i,j)\),因此对于所有顶点\(i,G_i\)都是以\(i\)为根的最短路径树。
23.2-4
可以知道,这个对\(d_{ij}^{(k)}\)的更新本质上是来自\(\{d_{ik}^{(k)}+d_{kj}^{(k)},d_{ik}^{(k-1)}+d_{kj}^{(k-1)},d_{ik}^{(k)}+d_{kj}^{(k-1)},d_{ik}^{(k-1)}+d_{kj}^{(k)}\}\)这\(4\)组值中的某一个,我们将通过证明\(d_{ik}^{(k-1)}=d_{ik}^{(k)},d_{kj}^{(k-1)}=d_{kj}^{(k)}\),从而说明这个更新是正确的。
考虑先证明\(d_{ik}^{(k-1)}=d_{ik}^{(k)}\)。根据\(d_{ij}^{(k)}\)的定义:从\(i\)到\(j\)的路径中,中间节点只包含节点\(1,2,\dots,k\)的最短路径。由于\(k\)是这条最短路径中的一个端点。\(k\)不在\(d_{ik}^{(k-1)}\)中,如果再尝试多途经一个节点\(k\),那么来自路径\(d_{ik}^{(k)}\)的最短路径必定不会劣于\(d_{ik}^{(k-1)}\)(因为\(d_{ik}^{(k-1)}\)是\(d_{ik}^{(k)}\)的一个子问题)。因此有\(d_{ik}^{(k-1)}\ge d_{ik}^{(k)}\)。如果\(k\)是从\(i\)到\(k\)这条路径的一个中间节点,那么路径上就会形成环,因此有\(d_{ik}^{(k-1)}\le d_{ik}^{(k)}\)。从而得出\(d_{ik}^{(k-1)}=d_{ik}^{(k)}\)。
可以用类似的证明方式,得到\(d_{kj}^{(k-1)}=d_{kj}^{(k)}\)。最终可知,这种更新方式是正确的。
23.2-5
由这个方式构造出来的矩阵是正确的。
此处仅讨论\(d_{ij}^{(k-1)}=d_{ik}^{(k-1)}+d_{kj}^{(k-1)}\)时的这种情况,因为如果等号不成立,情况和方程23.8时的一致。当第\(k\)轮循环结束时,保证有\(d_{ij}^{(k)}=d_{i,\pi_{ij}}^{(k-1)}+d_{\pi_{ij},j}^{(k-1)}\)。
本题对应的情况是\(\pi_{ij}^{(k)}=\pi_{kj}^{(k-1)}\)。由于\(d_{ij}^{(k-1)}=d_{ij}^{(k)}=d_{ik}^{(k-1)}+d_{kj}^{(k-1)}\),因此\(k\)也可以作为从\(i\)到\(j\)某条最短路径中的一个节点,由于\(d_{kj}^{(k-1)}\)也是取自某条从\(k\)到\(j\)最短路径的长度,作为一条子路径,它的前驱\(\pi_{kj}^{(k-1)}\)也适用于\(\pi_{ij}^{(k)}\)。
23.2-6
如果其最终输出\(D^{(n)}\)的主对角线上存在负数,那么说明\(G\)中存在负环。因为某次\(d^{k-1}_{ik}+d^{k-1}_{ki}<0\)的更新导致了主对角线上\(d^{k}_{ii}\)的值小于\(0\)。
23.2-7
由于Floyd-Warshall算法是从小到大插入中间节点\(k\)来求解最短路径的,因此如果节点\(k\)确实对从\(i\)到\(j\)的路径有实在的贡献,那么\(\phi^{(k)}_{ij}=k\),否则有\(\phi^{(k)}_{ij}=\phi^{(k-1)}_{ij}\),也就是沿用上一次迭代的结果。更正式地可以将\(\Phi^{(k)}\)写成:
\(\phi^{(k)}_{ij}= \left \{\begin{aligned} &k & & \text{if}\quad d^{(k-1)}_{ij} > d^{(k-1)}_{ik}+d^{(k-1)}_{kj} \\ &\phi^{(k-1)}_{ij} & & \text{if}\quad d^{(k-1)}_{ij} \le d^{(k-1)}_{ik}+d^{(k-1)}_{kj} \\ \end{aligned}\right.\)
那么可以将Floyd-Warshall算法进行改写以求出\(\Phi\),由FLOYD-WARSHALL'''
给出:
1 | FLOYD-WARSHALL'''(W, n) |
修改后的PRINT-ALL-PAIRS-SHORTEST-PATH
由程序PRINT-ALL-PAIRS-SHORTEST-PATH'
给出,它需要调用一个子程序AUX-PRINT-PATH
来保证路径能够被正确遍历。
1 | // 这个函数用来打印除了起点s和终点t以外的所有点。 |
表\(Φ\)和矩阵链乘所得到的表\(s\)是一样的,它们表示的内容都是当前最优情况下,对对路径/乘法阶段的最优划分。然而,\(\Phi\)表的路径追踪比\(s\)表难,因为\(\Phi\)表中的元素并不能直接获得特定的前驱或者是后继节点,只能向下一步步遍历。
23.2-8
枚举\(G=(V,E)\)中的每一个节点\(s\)进行BFS即可,被标记的节点都是能从\(s\)到达的节点。枚举完\(V\)中所有节点得到的结构恰好就是传递闭包。
整个算法由程序TRANSITIVE-CLOSURE''
给出。每进行一次BFS的时间复杂度为\(O(V+E)=O(E)\),因此进行\(|V|\)次BFS的时间复杂度为\(O(VE)\)。
1 | TRANSITIVE-CLOSURE''(G) |
23.2-9
考虑以\(3\)个步骤计算出有向图\(G=(V,E)\)的传递闭包。
先花费\(O(V+E)\)的时间求出\(G\)的强连通分量,再以\(O(V+E)\)的时间计算出这些强连通分量的分量图\(G^{SCC}=(V^{SCC},E^{SCC})\)。注意到,\(|V^{SCC}|\le |V|,|E^{SCC}|\le |E|\),并且\(G^{SCC}\)是一个有向无环图。
使用题中算法所描述的算法求解\(G^{SCC}\)的传递闭包\(G^{SCC\ast}=(V^{SCC},E^{SCC\ast})\),这将花费\(f(|V^{SCC}|,|E^{SCC}|)\)的时间。由于\(f\)是一个单调递增函数,因此说明只需要不超过\(f(|V|,|E|)\)的时间即可构造出\(G^{SCC\ast}\)。
考虑通过\(G^{SCC\ast}\)来构造\(G^{\ast}=(V,E^{\ast})\)。假设求解分量图完成后,强连通分量\(C_i\)表示图\(G\)中属于这个分量的所有节点,\(v_i\)是\(C_i\)在\(G^{SCC}\)上对应的节点。那么首先枚举\(C_i\)中的所有节点,并将它们成对的边添加到\(E^{\ast}\)中,每次枚举并添加一条边只需要\(O(1)\)的时间。对于\(\forall (v_i,v_j)\in E^{SCC\ast}\),\(\forall u\in v_i,v\in v_j,(u,v)\in E^{\ast}\),同样的,每次枚举并添加一条边只需要\(O(1)\)的时间。添加完所有边恰好需要\(O(V+E^{\ast})\)的时间。
因此,这\(3\)部分所需要花费的时间为\(f(|V|,|E|)+O(V+E)+O(V+E^{\ast})\),即可得到\(f(|V|,|E|)+O(V+E^{\ast})\)。