22.4-1 给出算法 TOPOLOGICAL-SORT 运行于图 22-8 上时所生成的结点次序。这里的所有假设和练习 22.3-2 一样。

ANSWER:

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

 

22.4-2 请给出一个线性时间的算法,算法的输入为一个有向无环图 G = (V, E) 以及两个结点 s 和 t,算法的输出是从结点 s 到结点 t 之间的简单路径的数量。例如,对于图 22-8 所示的有向无环图,从结点 p 到结点 v 一共有 4 条简单路径,分别是 pov、poryv、posryv 和 psryv。(本题仅要求计数简单路径的条数,而不要求将简单路径本身列举出来。)

ANSWER:给结点附加一个计数属性time,初始化 t.time = 1,其它的 time 均为 0 ,以 s 为源结点进行 DFS,一旦搜索到 t,则 t 马上着黑色(即不继续搜索 t 的后代)。每当结束一个结点的搜索,则该结点的 time 属性 = 该结点所指向的所有结点的 time 之和。最后 s.time 即路径条数。

如图 22-8 的 p 到 v,最后 v.time = 1, y.time = 1, r.time = 1, s.time = 1, o.time = 1, p.time。

 解法二

有向无环图G=(V,E),求其点s和e之间的路径数目。此题首先要以点s开始作DFS,得到从s为起点的所有可达点的一顶DFS树,但这个路径数目需要详细参详。

定义P(x),表示点s到点x的路径数目,P(s)=1,即s到自身有一条路径,其余的所有路径数目都初始化为0。

路径从s到达点x,则必须到达x的上一层结点,假设以x为终点的上一层结点有n个,即a1,a2,...,an,由加法定律可知P(x)= P(a1) + P(a2) + ... + P(an),这是一个从顶向下的递推过程,有点类似于动态规划。

综上,我们只要获取任意一点的入邻接表(也称逆邻接表),由图G获取其转置GT,其中保存着任意一点的上一层结点。然后再从顶向下递推,正好利用拓扑排序获得的序列,因为由拓扑排序的定义可以保证结点的顺序关系,因此递推有效。以下的算法步骤:

(1) 由图G获取其转置图GT,以得到所有点的入邻接表

(2) 以点s开始作DFS,得到从点s到达点e的拓扑序列

(3) 以此拓扑序列为顺序,逐个获取P值,最终得到P(e),即s到e的路径数目

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

 

图中实线为tree edge,曲线为forward和cross edge,从p到v的路径数目,递推过程如下:

P(p) = 1

P(o) = P(p) = 1

P(s) = P(p) + P(o)= 2

P(r) = P(o) +P(s) = 3

P(y) = P(r) = 3

P(v) = P(y) +P(o) = 4

步骤(1) 代码如下 

static int graph_add_edge(struct link_graph *G, int uindex, int vindex)
{
    struct link_edge *e = NULL;
    struct link_vertex *u = G->v + uindex;

    e = malloc(sizeof(struct link_edge));
    if (!e)
        return -1;
    e->vindex = vindex;
    e->type = EDGE_NONE;

    list_add(&e->node, &u->head);
    return 0;
}

struct link_graph* graph_transpos(struct link_graph *G)
{
    int i = 0;
    struct link_edge *e = NULL;
    struct link_vertex *u = NULL;
    struct link_graph *GT = NULL;

    GT = malloc(sizeof(struct link_graph));
    if (!GT)
        return NULL;
    GT->v = malloc(G->vcount * sizeof(struct link_vertex));
    if (!GT->v) {
        free(GT);
        return NULL;
    }

    GT->vcount = G->vcount;
    GT->ecount = G->ecount;
    for (i = 0;i < GT->vcount;i++) {
        u = GT->v + i;
        u->vindex = i;
        INIT_LIST_HEAD(&u->head);
    }

    for (i = 0;i < G->vcount;i++) {
        u = G->v + i;
        list_for_each_entry(e, &u->head, node) {
            graph_add_edge(GT, e->vindex, i);
        }
    }

    return GT;
}
View Code

相关文章:

  • 2021-06-16
  • 2022-12-23
  • 2021-09-09
  • 2022-12-23
  • 2021-06-10
  • 2021-05-28
  • 2022-12-23
猜你喜欢
  • 2022-01-06
  • 2021-11-24
  • 2022-12-23
  • 2021-10-19
  • 2022-02-03
  • 2021-05-06
相关资源
相似解决方案