给定带权有向图$\Gcal = (\Vcal, \Ecal)$,其中$\Vcal$为边集、$\Ecal$为点集
边上的权重由函数$w: \Ecal \mapsto \Rbb$给出,允许权重为负,但没有负环
对任意一对点$u,v \in \Vcal$,求$u$到$v$的最短路径
对于全结点对问题全部采用矩阵的表示形式更方便处理
设$n = |\Vcal|$,点的名字就是$1, 2, \ldots, n$
邻接矩阵$\Wv = [w_{ij}]_{1 \le i,j \le n}$,其中$w_{ij} = \begin{cases} 0, & i=j \\ w(i,j), & (i,j) \in \Ecal \\ \infty, & (i,j) \not \in \Ecal \end{cases}$
$d_v^{(k)}$:从$s$到$v$经过不超过$k$条边的最短路径的长度
$$ \begin{align*} \quad d_v^{(k)} = \begin{cases} \infty, & k = 0 \\ \min \{ d_v^{(k-1)}, ~ \min_{u \ne v} \{ d_u^{(k-1)} + w(u,v) \} \}, & k \ge 1 \end{cases} \end{align*} $$
$\ell_{ij}^{(m)}$:从$i$到$j$经过不超过$m$条边的最短路径的长度
$$ \begin{align*} \quad \ell_{ij}^{(m)} & = \begin{cases} \infty, & m = 0 \\ \min \{ \ell_{ij}^{(m-1)}, ~ \min_{k \ne j} \{ \ell_{ik}^{(m-1)} + w_{kj} \} \}, & m \ge 1 \end{cases} \\ & = \begin{cases} \infty, & m = 0 \\ \min_k \{ \ell_{ik}^{(m-1)} + w_{kj} \}, & m \ge 1 \end{cases} \end{align*} $$
$$ \begin{align*} \quad \ell_{ij}^{(m)} = \begin{cases} \infty, & m = 0 \\ \min_k \{ \ell_{ik}^{(m-1)} + w_{kj} \}, & m \ge 1 \end{cases} \end{align*} $$
def sp_all_dp(): l = np.array(w, copy=True) p = init_p() # 初始化前驱矩阵 for _ in range(n - 2): ll = np.array(l, copy=True) for i in range(n): for j in range(n): for k in range(n): if ll[i, k] + w[k, j] < l[i, j]: l[i, j] = ll[i, k] + w[k, j] # 更新L p[i, j] = k + 1 # 更新前驱 return l, p
四重 for 循环时间复杂度$\Theta(n^4)$,二维表格空间复杂度$\Theta(n^2)$
$$ \begin{align*} \quad \ell_{ij}^{(m)} & = \begin{cases} \infty, & m = 0 \\ \min_k \{ \ell_{ik}^{(m-1)} + w_{kj} \}, & m \ge 1 \end{cases} \\[5px] \Lv^{(1)} & = \begin{bmatrix} 0 & 3 & 8 & \infty & -4 \\ \infty & 0 & \infty & 1 & 7 \\ \infty & 4 & 0 & \infty & \infty \\ 2 & \infty & -5 & 0 & \infty \\ \infty & \infty & \infty & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(1)} & = \begin{bmatrix} - & 1 & 1 & - & 1 \\ - & - & - & 2 & 2 \\ - & 3 & - & - & - \\ 4 & - & 4 & - & - \\ - & - & - & 5 & - \end{bmatrix} \end{align*} $$
$$ \begin{align*} \quad \ell_{ij}^{(m)} & = \begin{cases} \infty, & m = 0 \\ \min_k \{ \ell_{ik}^{(m-1)} + w_{kj} \}, & m \ge 1 \end{cases} \\[5px] \Lv^{(2)} & = \begin{bmatrix} 0 & 3 & 8 & \class{blue}{2} & -4 \\ \class{blue}{3} & 0 & \class{blue}{-4} & 1 & 7 \\ \infty & 4 & 0 & \class{blue}{5} & \class{blue}{11} \\ 2 & \class{blue}{-1} & -5 & 0 & \class{blue}{-2} \\ \class{blue}{8} & \infty & \class{blue}{1} & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(2)} & = \begin{bmatrix} - & 1 & 1 & \class{blue}{5} & 1 \\ \class{blue}{4} & - & \class{blue}{4} & 2 & 2 \\ - & 3 & - & \class{blue}{2} & \class{blue}{2} \\ 4 & \class{blue}{3} & 4 & - & \class{blue}{1} \\ \class{blue}{4} & - & \class{blue}{4} & 5 & - \end{bmatrix} \end{align*} $$
$$ \begin{align*} \quad \ell_{ij}^{(m)} & = \begin{cases} \infty, & m = 0 \\ \min_k \{ \ell_{ik}^{(m-1)} + w_{kj} \}, & m \ge 1 \end{cases} \\[5px] \Lv^{(3)} & = \begin{bmatrix} 0 & 3 & \class{blue}{-3} & 2 & -4 \\ 3 & 0 & -4 & 1 & \class{blue}{-1} \\ \class{blue}{7} & 4 & 0 & 5 & 11 \\ 2 & -1 & -5 & 0 & -2 \\ 8 & \class{blue}{5} & 1 & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(3)} & = \begin{bmatrix} - & 1 & \class{blue}{4} & 5 & 1 \\ 4 & - & 4 & 2 & \class{blue}{1} \\ \class{blue}{4} & 3 & - & 2 & 2 \\ 4 & 3 & 4 & - & 1 \\ 4 & \class{blue}{3} & 4 & 5 & - \end{bmatrix} \end{align*} $$
$$ \begin{align*} \quad \ell_{ij}^{(m)} & = \begin{cases} \infty, & m = 0 \\ \min_k \{ \ell_{ik}^{(m-1)} + w_{kj} \}, & m \ge 1 \end{cases} \\[5px] \Lv^{(4)} & = \begin{bmatrix} 0 & \class{blue}{1} & -3 & 2 & -4 \\ 3 & 0 & -4 & 1 & -1 \\ 7 & 4 & 0 & 5 & \class{blue}{3} \\ 2 & -1 & -5 & 0 & -2 \\ 8 & 5 & 1 & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(4)} & = \begin{bmatrix} - & \class{blue}{3} & 4 & 5 & 1 \\ 4 & - & 4 & 2 & 1 \\ 4 & 3 & - & 2 & \class{blue}{1} \\ 4 & 3 & 4 & - & 1 \\ 4 & 3 & 4 & 5 & - \end{bmatrix} \end{align*} $$
矩阵乘法$\Av \leftarrow \Av \cdot \Bv$ vs. 最短路径$\Lv \leftarrow \Lv \circ \Wv$
for i in range(n): for j in range(n): for k in range(n): a[i,j] = a[i,j] + a[i,k] * b[k,j] for i in range(n): for j in range(n): for k in range(n): l[i,j] = min(l[i,j], l[i,k] + w[k,j])
二元运算$\circ$也有结合律!
注意初始时$\Lv^{(1)} = \Wv$,计算$\Lv^{(n)}$最外层循环迭代$\Theta(n)$轮
$$ \begin{align*} \quad \Lv^{(1)} & = \Wv \\ \Lv^{(2)} & = \Lv^{(1)} \circ \Wv = \Wv^2 \\ \Lv^{(3)} & = \Lv^{(2)} \circ \Wv = \Wv^3 \\ \Lv^{(4)} & = \Lv^{(3)} \circ \Wv = \Wv^4 \\ \end{align*} $$
利用结合律最外层循环只需$\Theta(\lg n)$轮,总时间复杂度$\Theta(n^3 \lg n)$
$$ \begin{align*} \quad \Lv^{(1)} & = \Wv \\ \Lv^{(2)} & = \Wv^2 = \Lv^{(1)} \circ \Lv^{(1)} \\ \Lv^{(4)} & = \Wv^4 = \Lv^{(2)} \circ \Lv^{(2)} \\ \Lv^{(8)} & = \Wv^8 = \Lv^{(4)} \circ \Lv^{(4)} \end{align*} $$
def sp_all_dp_plus(): l = np.array(w, copy=True) p = init_p() # 初始化前驱矩阵 m = 1 while m < n - 1: ll = np.array(l, copy=True) for i in range(n): for j in range(n): for k in range(n): if ll[i, k] + ll[k, j] < l[i, j]: l[i, j] = ll[i, k] + ll[k, j] # 更新L p[i, j] = p[k, j] # 更新前驱 m *= 2 return l, p
$\ell_{ij}^{(m)}$:从$i$到$j$经过不超过$m$条边的最短路径的长度
$$ \begin{align*} \quad \ell_{ij}^{(m)} = \begin{cases} \infty, & m = 0 \\ \min_k \{ \ell_{ik}^{(m-1)} + w_{kj} \}, & m \ge 1 \end{cases} \end{align*} $$
$d_{ij}^{(k)}$:从$i$到$j$中间结点属于集合$\{1,2, \ldots,k\}$的最短路径的长度
$$ \begin{align*} \quad d_{ij}^{(k)} = \begin{cases} w_{ij}, & k = 0 \\ \min \{ d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \}, & k \ge 1 \end{cases} \end{align*} $$
$$ \begin{align*} \quad d_{ij}^{(k)} = \begin{cases} w_{ij}, & k = 0 \\ \min \{ d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \}, & k \ge 1 \end{cases} \end{align*} $$
def floyd_warshall(): d = np.array(w, copy=True) p = init_p() # 初始化前驱矩阵 for k in range(n): dd = np.array(d, copy=True) for i in range(n): for j in range(n): if dd[i, k] + dd[k, j] < d[i, j]: d[i, j] = dd[i, k] + dd[k, j] # 更新d p[i, j] = p[k, j] # 更新前驱 print(d) print(p) return d, p
三重 for 循环时间复杂度$\Theta(n^3)$,二维表格空间复杂度$\Theta(n^2)$
$$ \begin{align*} \quad d_{ij}^{(k)} & = \begin{cases} w_{ij}, & k = 0 \\ \min \{ d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \}, & k \ge 1 \end{cases} \\[5px] \Dv^{(0)} & = \begin{bmatrix} 0 & 3 & 8 & \infty & -4 \\ \infty & 0 & \infty & 1 & 7 \\ \infty & 4 & 0 & \infty & \infty \\ 2 & \infty & -5 & 0 & \infty \\ \infty & \infty & \infty & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(0)} & = \begin{bmatrix} - & 1 & 1 & - & 1 \\ - & - & - & 2 & 2 \\ - & 3 & - & - & - \\ 4 & - & 4 & - & - \\ - & - & - & 5 & - \end{bmatrix} \end{align*} $$
$$ \begin{align*} \quad d_{ij}^{(k)} & = \begin{cases} w_{ij}, & k = 0 \\ \min \{ d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \}, & k \ge 1 \end{cases} \\[5px] \Dv^{(1)} & = \begin{bmatrix} 0 & 3 & 8 & \infty & -4 \\ \infty & 0 & \infty & 1 & 7 \\ \infty & 4 & 0 & \infty & \infty \\ 2 & \class{blue}{5} & -5 & 0 & \class{blue}{-2} \\ \infty & \infty & \infty & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(1)} & = \begin{bmatrix} - & 1 & 1 & - & 1 \\ - & - & - & 2 & 2 \\ - & 3 & - & - & - \\ 4 & \class{blue}{1} & 4 & - & \class{blue}{1} \\ - & - & - & 5 & - \end{bmatrix} \end{align*} $$
$$ \begin{align*} \quad d_{ij}^{(k)} & = \begin{cases} w_{ij}, & k = 0 \\ \min \{ d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \}, & k \ge 1 \end{cases} \\[5px] \Dv^{(2)} & = \begin{bmatrix} 0 & 3 & 8 & \class{blue}{4} & -4 \\ \infty & 0 & \infty & 1 & 7 \\ \infty & 4 & 0 & \class{blue}{5} & \class{blue}{11} \\ 2 & 5 & -5 & 0 & -2 \\ \infty & \infty & \infty & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(2)} & = \begin{bmatrix} - & 1 & 1 & \class{blue}{2} & 1 \\ - & - & - & 2 & 2 \\ - & 3 & - & \class{blue}{2} & \class{blue}{2} \\ 4 & 1 & 4 & - & 1 \\ - & - & - & 5 & - \end{bmatrix} \end{align*} $$
$$ \begin{align*} \quad d_{ij}^{(k)} & = \begin{cases} w_{ij}, & k = 0 \\ \min \{ d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \}, & k \ge 1 \end{cases} \\[5px] \Dv^{(3)} & = \begin{bmatrix} 0 & 3 & 8 & 4 & -4 \\ \infty & 0 & \infty & 1 & 7 \\ \infty & 4 & 0 & 5 & 11 \\ 2 & \class{blue}{-1} & -5 & 0 & -2 \\ \infty & \infty & \infty & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(3)} & = \begin{bmatrix} - & 1 & 1 & 2 & 1 \\ - & - & - & 2 & 2 \\ - & 3 & - & 2 & 2 \\ 4 & \class{blue}{3} & 4 & - & 1 \\ - & - & - & 5 & - \end{bmatrix} \end{align*} $$
$$ \begin{align*} \quad d_{ij}^{(k)} & = \begin{cases} w_{ij}, & k = 0 \\ \min \{ d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \}, & k \ge 1 \end{cases} \\[5px] \Dv^{(4)} & = \begin{bmatrix} 0 & 3 & \class{blue}{-1} & 4 & -4 \\ \class{blue}{3} & 0 & \class{blue}{-4} & 1 & \class{blue}{-1} \\ \class{blue}{7} & 4 & 0 & 5 & \class{blue}{3} \\ 2 & -1 & -5 & 0 & -2 \\ \class{blue}{8} & \class{blue}{5} & \class{blue}{1} & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(4)} & = \begin{bmatrix} - & 1 & \class{blue}{4} & 2 & 1 \\ \class{blue}{4} & - & \class{blue}{4} & 2 & \class{blue}{1} \\ \class{blue}{4} & 3 & - & 2 & \class{blue}{1} \\ 4 & 3 & 4 & - & 1 \\ \class{blue}{4} & \class{blue}{3} & \class{blue}{4} & 5 & - \end{bmatrix} \end{align*} $$
$$ \begin{align*} \quad d_{ij}^{(k)} & = \begin{cases} w_{ij}, & k = 0 \\ \min \{ d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \}, & k \ge 1 \end{cases} \\[5px] \Dv^{(5)} & = \begin{bmatrix} 0 & \class{blue}{1} & \class{blue}{-3} & \class{blue}{2} & -4 \\ 3 & 0 & -4 & 1 & -1 \\ 7 & 4 & 0 & 5 & 3 \\ 2 & -1 & -5 & 0 & -2 \\ 8 & 5 & 1 & 6 & 0 \end{bmatrix} \\[5px] \Pv^{(5)} & = \begin{bmatrix} - & \class{blue}{3} & \class{blue}{4} & \class{blue}{5} & 1 \\ 4 & - & 4 & 2 & 1 \\ 4 & 3 & - & 2 & 1 \\ 4 & 3 & 4 & - & 1 \\ 4 & 3 & 4 & 5 & - \end{bmatrix} \end{align*} $$
输入:有向图$\Gcal = (\Vcal, \Ecal)$
输出:传递闭包$\Gcal^* = (\Vcal, \Ecal^*)$,其中$\Ecal^* = \{ (i,j) \mid \exists p: i \overset{p}{\rightsquigarrow} j \}$
方法一:给$\Ecal$中每条边赋权重$1$,然后运行 Floyd-Warshall 算法
方法二:引入矩阵$\Tv = [t_{ij}]_{1 \le i,j \le n}$,其中$t_{ij} = \begin{cases} 1, & \exists p: i \overset{p}{\rightsquigarrow} j \\ 0, & \text{其它} \end{cases}$
$$ \begin{align*} \quad t_{ij}^{(0)} & = \begin{cases} 0, & i \ne j \text{ 且 } (i,j) \not \in \Ecal \\ 1, & i = j \text{ 或 } (i,j) \in \Ecal \end{cases} \\[5px] t_{ij}^{(k)} & = t_{ij}^{(k-1)} \vee (t_{ik}^{(k-1)} \wedge t_{kj}^{(k-1)}) \end{align*} $$
$\min \rightarrow \vee$、$+ \rightarrow \wedge$,逻辑运算比算术运算快,空间需求也较小
$$ \begin{align*} \quad d_{ij}^{(k)} & = \min \{ d_{ij}^{(k-1)}, d_{ik}^{(k-1)} + d_{kj}^{(k-1)} \} \\ t_{ij}^{(k)} & = t_{ij}^{(k-1)} \vee (t_{ik}^{(k-1)} \wedge t_{kj}^{(k-1)}) \end{align*} $$
def transitive_closure(): t = np.zeros((n, n), dtype="int") for i in range(n): for j in range(n): if i == j or w[i, j] == 1: t[i, j] = 1 for k in range(n): for i in range(n): for j in range(n): t[i, j] = t[i, j] | (t[i, k] & t[k, j]) # 更新t return t
三重 for 循环时间复杂度$\Theta(n^3)$,二维表格空间复杂度$\Theta(n^2)$
$$ \begin{align*} t_{ij}^{(0)} & = \begin{cases} 0, & i \ne j \text{ 且 } (i,j) \not \in \Ecal \\ 1, & i = j \text{ 或 } (i,j) \in \Ecal \end{cases} \\[10px] t_{ij}^{(k)} & = t_{ij}^{(k-1)} \vee (t_{ik}^{(k-1)} \wedge t_{kj}^{(k-1)}) \\[10px] \Tv^{(0)} & = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 1 & 1 \\ 0 & 1 & 1 & 0 \\ 1 & 0 & 1 & 1 \end{bmatrix}, ~ \Tv^{(1)} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 1 & 1 \\ 0 & 1 & 1 & 0 \\ 1 & 0 & 1 & 1 \end{bmatrix} \\[10px] \Tv^{(2)} & = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 1 & 1 \\ 0 & 1 & 1 & \class{blue}{1} \\ 1 & 0 & 1 & 1 \end{bmatrix}, ~ \Tv^{(3)} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 1 & 1 \\ 0 & 1 & 1 & 1 \\ 1 & \class{blue}{1} & 1 & 1 \end{bmatrix}, ~ \Tv^{(4)} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ \class{blue}{1} & 1 & 1 & 1 \\ \class{blue}{1} & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 \end{bmatrix} \end{align*} $$
Floyd-Warshall 算法的时间复杂度是$\Theta(\shu\Vcal\shu^3)$
| 实现 | 一般时间复杂度 | 稠密图 | 稀疏图 |
---|---|---|---|---|
Bellman-Ford | | $\Theta(\shu\Vcal\shu \shu\Ecal\shu)$ | $\Theta(\shu\Vcal\shu^3)$ | $O(\shu\Vcal\shu^2)$ |
Dijkstra | 线性数组 | $\Theta(\shu\Vcal\shu^2 + \shu\Ecal\shu)$ | $\Theta(\shu\Vcal\shu^2)$ | $\Theta(\shu\Vcal\shu^2)$ |
二叉堆 | $\Theta((\shu\Vcal\shu + \shu\Ecal\shu) \lg \shu\Vcal\shu)$ | $\Theta(\shu\Vcal\shu^2 \lg \shu\Vcal\shu)$ | $\Theta(\shu\Vcal\shu \lg \shu\Vcal\shu)$ | |
斐波那契堆 | $\Theta(\shu\Vcal\shu \lg \shu\Vcal\shu + \shu\Ecal\shu)$ | $\Theta(\shu\Vcal\shu^2)$ | $\Theta(\shu\Vcal\shu \lg \shu\Vcal\shu)$ |
对于稀疏图,以每个点为源点运行 Dijkstra 算法$\Theta(\shu\Vcal\shu^2 \lg \shu\Vcal\shu)$
有负边怎么办?Dijkstra 算法不能处理有负边的图
构造新的权重函数$\what: \Ecal \mapsto \class{blue}{\Rbb^+}$且满足路径等价性:$p$在使用$w$时是最短路径当且仅当其在使用$\what$时也是最短路径
引入函数$h: \Vcal \mapsto \Rbb$,定义$\what(u,v) = w(u,v) + h(u) - h(v)$
设$p = \langle v_0, v_1, \ldots, v_k \rangle$是$v_0$到$v_k$的任意一条路径
$$ \begin{align*} \quad \sum_{i=1}^k \what(v_{i-1}, v_i) = \sum_{i=1}^k w(v_{i-1}, v_i) + h(v_0) - h(v_k) \end{align*} $$
固定$v_0$和$v_k$,对任意路径,新旧权重函数引起的变化是常数,不依赖中间经过的点,因此路径等价性满足
令$v_0=v_k$易知$p$在使用$w$时是负环当且仅当在使用$\what$时也是负环
构造新的权重函数$\what: \Ecal \mapsto \class{blue}{\Rbb^+}$且满足路径等价性:$p$在使用$w$时是最短路径当且仅当其在使用$\what$时也是最短路径
引入函数$h: \Vcal \mapsto \Rbb$,定义$\what(u,v) = w(u,v) + h(u) - h(v)$
如何设计$h$保证$\what$的非负性呢?
$0 \le \what(u,v) = w(u,v) + h(u) - h(v) \Longleftrightarrow h(v) \le h(u) + w(u,v)$
联想到三角不等式$\delta(s,v) \le \delta(s,u) + w(u,v)$,可取$h(v) = \delta(s,v)$
引入新结点$0$,并有权重为零的边指向其它所有点
$0$没有入边,不会影响其它点间的最短路径,也不会产生新的环
以$0$为源点运行 Bellman-Ford 算法
g = { "1": {"2": 3, "3": 8, "5": -4}, # w(1,2) = 3, w(1,3) = 8, w(1,5) = -4 "2": {"4": 1, "5": 7}, # w(2,4) = 1, w(2,5) = 7 "3": {"2": 4}, # w(3,2) = 4 "4": {"1": 2, "3": -5}, # w(4,1) = 2, w(4,3) = -5 "5": {"4": 6}, # w(5,4) = 6 } g["0"] = {"1": 0, "2": 0, "3": 0, "4": 0, "5": 0} # 添加新结点0 h = bellman_ford(s="0") # 以0为源点运行Bellman-Ford算法 for u in g: for v in g[u]: g[u][v] += h[u] - h[v] # 根据h重新给边赋权 D = dict() for u in g: if u != "0": D[u] = dijkstra(u) # 以每个结点为源点运行Dijkstra算法 del D[u]["0"] del g["0"] for u in g: for v in g: D[u][v] += h[v] - h[u] # 还原原权重下的最短路径长度 print(D) ------------------------------ '1': {'1': 0, '2': 1, '3': -3, '4': 2, '5': -4} '2': {'1': 3, '2': 0, '3': -4, '4': 1, '5': -1} '3': {'1': 7, '2': 4, '3': 0, '4': 5, '5': 3 } '4': {'1': 2, '2': -1, '3': -5, '4': 0, '5': -2} '5': {'1': 8, '2': 5, '3': 1, '4': 6, '5': 0 }
算法导论 3rd
计算题:24.1-1、24.4-1、25.2-1
设计、证明题:24.1-3、24-3、25.2-7
思考题:25.2-6