算法导论22.3深度优先搜索 练习总结 (转载)

22.3-1 画一个 3*3 的网格,行和列的抬头分别标记为白色、灰色和黑色,对于每个表单元 (i, j),请指出对有向图进行深度优先搜索的过程中,是否可能存在一条边,链接一个颜色为 i 的结点和一个颜色为 j 的结点。对于每种可能的边,指明该种边的类型。另外,请针对无向图的深度优先搜索再制作一张这样的网格。

ANSWER:

 

22.3-2 给出深度优先搜索算法在图 22-6 上的运行过程。假定深度优先搜索算法的第 5~7 行的 for 循环是以字母表顺序依次处理每个结点,假定每条邻接链表皆以字母表顺序对立面的结点进行了排序。请给出每个结点的发信啊时间和完成时间,并给出每条边的分类。

ANSWER:

 

22.3-3 给出图 22-4 的深度优先搜索的括号化结构。

ANSWER:

 

22.3-4 证明:使用单个位来存放每个结点的颜色已经足够。这一点可以通过证明如下事实来得到:如果将 DFS-VISIT 的第 8 行删除,DFS 给出的结果相同。

ANSWER:和 22.2-3 类似,事实上,在 DFS-VISIT 中,在递归过程中,系统会调用栈存放未被检测的结点,并不一定需要将结点着黑色和灰色来区别,因为程序中并没有检测结点是否黑色的命令。着黑白灰是为了易于观察。

22.3-5 证明边 (u, v) 是:

a. 树边或前向边当且仅当 u.d < v.d < v.f < u.f。

b. 后向边当且仅当 v.d ≤ u.d < u.f ≤ v.f。

c. 横向边当且仅当 v.d < v.f < u.d < u.f。

ANSWER:由于深度优先搜索满足括号化结构,将结点的关系以括号化结构表示易证明此关系。

22.3-6 证明:在无向图中,根据深度优先搜索算法是先搜索 (u, v) 还是先搜索 (v, u) 来将边 (u, v) 分类为树边或者后向边,与根据分类列表中的 4 种类型的次序进行分类是等价的。

ANSWER:有向图是将无向图的一条边变成有方向的两条边。所以本质上分类标准是等价的。

22.3-7 请重写 DFS 算法的伪代码,以便使用栈来消除递归调用。

ANSWER:

DFS-VISIT:
    STACK.push(u)
    while ! STACK.empty
        u = STACK.top
        if u.color == GRAY
            u.color = BLACK
            time = time + 1
            u.f = time
            STACK.pop
            continue
        if u.color == WHITE
            u.color = GRAY
            time = time + 1
            u.d = time
        for each v ∈ G:Adj[u]
            v.π = u
            STACK.push(u)

22.3-8 请给出如下猜想的一个反例:如果有向图 G 包含一条从结点 u 到结点 v 的路径,并且在对图 G 进行深度优先搜索时有 u.d < v.d,则结点 v 是结点 u 在深度优先森林中的一个后代。

ANSWER:

 

22.3-9 请给出如下猜想的一个反例:如果有向图 G 包含一条从结点 u 到结点 v 的路径,则任何对图 G 的深度优先搜索都将导致 v.d ≤ u.f。

ANSWER:和 22.3-8 反例的图一样。

22.3-10 修改深度优先搜索的伪代码,让其打印出有向图 G 的每条边及其分类。并指出,如果图 G 是无向图, 要进行何种修改才能达到相同的效果。

ANSWER:在完成 DFS 之后对有向图 G 的边进行遍历,按照 22.3-5的结论的规则。

CLASSIFY-EDGE(G):
    for each vertex u ∈ G.V
        for each v ∈ G:Adj[u]
            if v.π == u:
                edge(u, v).c = T
            else if u.d < v.d < v.f < u.f :
                edge(u, v).c = F
            else if v.d ≤ u.d < u.f ≤ v.f:
                edge(u, v).c = B
            else:
                edge(u, v).c = C

无向图:只需要把三个 else 改成一个 else,分类为后向边即可。

22.3-11 请解释有向图的一个结点 u 怎样才能成为深度优先树中的唯一结点,即使结点 u 同时有入边和出边。

ANSWER:

 

22.3-12 证明:我们可以在无向图 F 上使用深度优先搜索来获得图 G 的连通分量,并且深度优先森林所包含的数的棵数与 G 的连通分量数量相同。更准确地说,请给出如何修改深度优先搜索来让其每个结点赋予一个介于 1 和 k 之间的整数值 v.cc,这里 k 是 G 的连通分量数,使得 u.cc = v.cc 当且仅当结点 u 和结点 v 处于同一个连通分量中。

ANSWER:当执行 DFS 的第 5、6 行时,每跳入一次第 7 行,连通分量数加 1,在 DFS-VISIT 里遇到的结点的联通分量数相同。

联通分支的数量用ceil表示,代码修改如下

void Link_Graph::DFS()
{
    int u, ceil = 0;
    //对每个顶点初始化
    for(u = 1; u <= n; u++)
    {
        V[u].color = WHITE;
        V[u].p =  NULL;
    }
    //时间戳初始化
    time = 0;
    //依次检索V中的顶点,发现白色顶点时,调用DFS_Visit访问该顶点
    for(u = 1; u <= n; u++)
    {
        if(V[u].color == WHITE)
        {
            ceil++;
            DFS_Visit(u, ceil);
        }
    }
}

void Link_Graph::DFS_Visit(int u, int ceil)
{
    int v;
    Edge *e;
    //将u置为灰色
    V[u].color = GRAY;
    //使全局变量time增值
    time++;
    //将time的新值记录为发现时间
    V[u].d = time;
    e = V[u].head;
    while(e)
    {
        v = e->end;
        //如果顶点为白色
        if(V[v].color == WHITE)
        {
            //递归访问顶点
            V[v].p = u;
            DFS_Visit(v, ceil);
            //树边
            e->type = TREE;
        }
        else if(V[v].color == GRAY)
        {
            //反向边
            e->type = BACK;
        }
        else if(V[v].color == BLACK)
        {
            //正向边
            if(V[u].d < V[v].d)
                e->type = FORWARD;
            //交叉边
            else
                e->type = CROSS;
        }
        e = e->next;
    }
    //以u为起点的所有边都被探寻后,置u为黑色
    V[u].color = BLACK;
    V[u].ceil = ceil;
    //并将完成时间记录在f[u]中
    time++;
    V[u].f = time;
}

*22.3-13 对于有向图 G = (V, E) 来说,如果 u ~ v 以为这图 G 至多包含一条从 u 到 v 的简单路径,则图 G 是单连通图。请给出一个有效算法来判断一个有向图是否单连通图。

ANSWER:

单连通图没有正向边(向前边)

时间: 2024-10-13 16:58:21

算法导论22.3深度优先搜索 练习总结 (转载)的相关文章

算法导论22章基本的图算法 思考题总结 (转载)

22-1 (以广度优先搜索来对图的边进行分类)深度优先搜索将图中的边分类为树边.后向边.前向边和横向边.广度优先搜索也可以用来进行这种分类.具体来说,广度优先搜索将从源结点可以到达的边划分为同样的4种类型. a.证明在对无向图进行的广度优先搜索中,下面的性质成立: 1.不存在后向边,也不存在前向边. 2.对于每条树边(u, v),我们有v.d = u.d + 1. 3.对于每条横向边(u, v),我么有v.d = u.d 或 v.d = u.d + 1. b.证明在对有向图进行广度优先搜索时,下

算法_图的深度优先搜索和广度优先搜索

一.图的基本数据结构 图是由一组顶点和一组能够将两个顶点相互连接的边所构成的,一般使用0~V-1这样的数字形式来表示一张含有V个顶点的图.用v-w来指代一张图的边,由于是无向图,因此v-w和w-v是同一种边的两种表示方法.无向图是指边没有方向的图结构在无向图中,边仅仅表示的是两个顶点之间的连接.图的数据结构的可视化如下图所示(其中边上的箭头没有任何意义): 当两个顶点通过一条边相互连接,则称这两个顶点是相邻的.某个顶点的度数即为依附它的边的总数.当两个顶点之间存在一条连接双方的路径的时候,称为这

算法导论22.4拓扑排序 练习总结 (转载)

22.4-1 给出算法 TOPOLOGICAL-SORT 运行于图 22-8 上时所生成的结点次序.这里的所有假设和练习 22.3-2 一样. ANSWER:   22.4-2 请给出一个线性时间的算法,算法的输入为一个有向无环图 G = (V, E) 以及两个结点 s 和 t,算法的输出是从结点 s 到结点 t 之间的简单路径的数量.例如,对于图 22-8 所示的有向无环图,从结点 p 到结点 v 一共有 4 条简单路径,分别是 pov.poryv.posryv 和 psryv.(本题仅要求计

基础算法(四)——深度优先搜索

一般情况下,深度有限搜索也适用于图的遍历,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次. [重点]BFS和DFS的区别:说白了,也就是如图1-13所示: [例]用DFS遍历如图1-14的图. 用DFS遍历结果为: 一般情况下,DFS可以用递归来实现,就像这样: 1 procedure dfs(k:integer); 2 begin 3 if 判断边界条件 then exit; 4 dfs(下一个搜索区

邻接链表线性时间去重 C代码 算法导论 22.1-4

这里利用直接寻址法去重,遍历链表,如果对应数组位置值为0,则修正为1,如果对应数组为1,则删除该节点.(数组初始化为0) 链表的一些操作都简单的实现了一下. #include <stdio.h> #include <stdlib.h> #include <malloc.h> struct Node{ int key; Node *next; }; struct List{ Node *head; }; typedef struct Node Node; typedef

算法导论.pdf

下载地址:网盘下载 内容简介  · · · · · · 在有关算法的书中,有一些叙述非常严谨,但不够全面:另一些涉及了大量的题材,但又缺乏严谨性.本书将严谨性和全面性融为一体,深入讨论各类算法,并着力使这些算法的设计和分析能为各个层次的读者接受.全书各章自成体系,可以作为独立的学习单元:算法以英语和伪代码的形式描述,具备初步程序设计经验的人就能看懂:说明和解释力求浅显易懂,不失深度和数学严谨性. 全书选材经典.内容丰富.结构合理.逻辑清晰,对本科生的数据结构课程和研究生的算法课程都是非常实用的教

POJ2488 深度优先搜索+回溯

POJ2488 题目 骑士按照下图所示的走法对棋盘进行巡逻,每个格子只允许巡逻一次,且必须巡逻所有格子.给定棋盘的行数p和列数q,输出一条骑士巡逻路径,若不存在这样一条路径,则输出impossible. 图1 骑士的8种走法 骑士巡逻问题的简化版本,是哈密顿路径问题的特殊形式,但是是线性时间内可以解决的\(^{[1]}\). Sample Input 3 1 1 2 3 4 3 Sample Output Scenario #1: A1 Scenario #2: impossible Scena

&quot;《算法导论》之‘图’&quot;:深度优先搜索、宽度优先搜索及连通分量

本文兼参考自<算法导论>及<算法>. 以前一直不能够理解深度优先搜索和广度优先搜索,总是很怕去碰它们,但经过阅读上边提到的两本书,豁然开朗,马上就能理解得更进一步.  1. 深度优先搜索  1.1 迷宫搜索 在<算法>这本书中,作者写了很好的一个故事.这个故事让我马上理解了深度优先搜索的思想. 如下图1-1所示,如何在这个迷宫中找到出路呢?方法见图1-2. 图1-1 等价的迷宫模型 探索迷宫而不迷路的一种古老办法(至少可以追溯到忒修斯和米诺陶的传说)叫做Tremaux搜

算法导论——DFS深度优先搜索

package org.loda.graph; import org.loda.structure.Stack; /** * * @ClassName: DFS * @Description: 深度优先搜索(无向图) * @author minjun * @date 2015年5月24日 上午4:02:24 * */ public class DFS { //原点 private int s; // visited[i]表示i节点是否被访问过 private boolean[] visited;