跳到主要内容

神戸大学 システム情報学研究科 2017年8月実施 専門科目 計算機科学 [2]

Author

祭音Myyura (co-authored with GPT 5.6 SOL)

Description

グラフの探索では、同一ノードを何度も探索しないよう注意が必要である。次の C プログラムにおいて、struct node は有向グラフのノードを表す。フィールド s,t がノードへの参照をもつとき、そのノードへの辺が存在する。id は識別子、visited は訪問回数である。dfs(node)node を起点として、st の順に再帰的な探索を行う。

#include <stdio.h>
#define BUFSIZE 20
typedef struct node {
struct node *s;
struct node *t;
int id; int visited;
} *node_tp;
struct node nodes[BUFSIZE];

void printNode(node_tp node) {
printf("(%d, %d)\n", node->id, node->visited);
}
void dfs(node_tp node) {
node_tp s = node->s;
node_tp t = node->t;
node->visited++;
printNode(node);
if (node->visited > 1) return;
if (s != NULL) dfs(s);
if (t != NULL) dfs(t);
}
void initNodes(int n) {
int i;
for (i = 0; i < n; i++) {
nodes[i].id = i; nodes[i].visited = 0;
nodes[i].s = nodes[i].t = NULL;
}
}
void link(node_tp node, node_tp s, node_tp t) {
node->s = s; node->t = t;
}

テストプログラムは次のとおりである。

void test0(void) {
initNodes(2);
link(&nodes[0], &nodes[1], NULL);
link(&nodes[1], NULL, &nodes[0]);
dfs(&nodes[0]);
}

void test1(void) {
initNodes(4);
link(&nodes[0], &nodes[3], &nodes[1]);
link(&nodes[1], &nodes[3], &nodes[2]);
link(&nodes[2], &nodes[3], NULL);
link(&nodes[3], NULL, &nodes[0]);
dfs(&nodes[1]);
}

void test2(void) {
int i;
initNodes(12);
for (i = 0; i < 5; i++) {
link(&nodes[i], &nodes[2*i+1], &nodes[2*i+2]);
}
dfs(&nodes[1]);
printf("---\n");
dfs(&nodes[0]);
}

void test3(void) {
int i;
initNodes(12);
for (i = 0; i < 10; i++) {
link(&nodes[i], &nodes[i+1], &nodes[i+2]);
}
dfs(&nodes[0]);
}

例として、test0 のグラフと標準出力は次のとおりである。

(0, 1)
(1, 1)
(0, 2)

以下の各問に答えよ。図の辺には、その参照が s,t のいずれであるかを示すこと。

  1. test1 が生成するグラフ(ノード 0〜3)と標準出力を示せ。

  2. test2 が生成するグラフ(ノード 0〜11)と標準出力を示せ。

  3. test3 が生成するグラフ(ノード 0〜11)を示せ。さらに、dfs 中の

    if (node->visited > 1) return;

    を完全に取り除いた場合、test3 の終了時に nodes[10] の訪問回数はいくつになるか。簡単な理由も述べよ。

题目描述

上述 C 程序用 st 两个指针表示有向边;dfs 先把当前结点的 visited 加一并输出,再在首次访问时依次沿 st 递归搜索。

  1. 画出 test1 生成的结点 0 至 3 的图,并写出标准输出。

  2. 画出 test2 生成的结点 0 至 11 的图,并写出标准输出。

  3. 画出 test3 生成的结点 0 至 11 的图。若完全删除 dfs 中的

    if (node->visited > 1) return;

    求程序结束时 nodes[10] 的访问次数,并简述理由。

Kai

(1)

dfsst の順に呼び出され、2 回目以降の訪問では直ちに戻る。したがって標準出力は

(1, 1)
(3, 1)
(0, 1)
(3, 2)
(1, 2)
(2, 1)
(3, 3)

である。

(2)

最初の探索でノード 11 の部分木を訪問し、その訪問情報を保ったままノード 00 から再び探索する。標準出力は

(1, 1)
(3, 1)
(7, 1)
(8, 1)
(4, 1)
(9, 1)
(10, 1)
---
(0, 1)
(1, 2)
(2, 1)
(5, 1)
(6, 1)

である。

(3)

条件文を削除すると、ノード 1010 はノード 00 から 1010 へ至る各経路につき 1 回訪問される。その経路数を pkp_k とすれば

p0=1,p1=1,pk=pk1+pk2(k2).p_0=1,\qquad p_1=1,\qquad p_k=p_{k-1}+p_{k-2}\quad(k\ge2).

よって

(p0,p1,,p10)=(1,1,2,3,5,8,13,21,34,55,89).(p_0,p_1,\ldots,p_{10}) =(1,1,2,3,5,8,13,21,34,55,\boxed{89}).

したがって nodes[10].visited の最終値は 89\boxed{89} である。