アルゴリズム設計マニュアルでは、BFSとDFSについて詳しく説明しています。本のdfsのコードには、エッジの二重処理を回避するかどうかを決定するときに問題があります。エラッタを見つけてコードにエラッタを適用しましたが、それでも洗練されたコードには二重処理エッジのチェックに問題があると思います。
洗練されたコードを次のように貼り付けます。
dfs(graph *g, int v) {
edgenode *p;
int y;
if (finished) return;
discovered[v] = TRUE;
time = time + 1;
entry_time[v] = time;
process_vertex_early(v);
p = g->edges[v];
while (p != NULL) {
/* temporary pointer */
/* successor vertex */
/* allow for search termination */
y = p->y;
if (discovered[y] == FALSE) {
parent[y] = v;
process_edge(v,y);
dfs(g,y);
}
else if (**(!processed[y] && parent[v] != y)** || (g->directed))
process_edge(v,y);
if (finished) return;
p = p->next;
}
process_vertex_late(v);
time = time + 1;
exit_time[v] = time;
processed[v] = TRUE;
}
問題があると思う場所は****でマークされています。
したがって、疑わしい場所は条件の1つです。無向グラフであると仮定して、の条件を無視することができます(g->directed)
。
さて、最初に焦点を当てましょうparent[v] != y
。parent[v] == y
もちろん、頂点yを処理するときにy-> vがすでに一度処理されているため、エッジv->yを再度処理する必要がない場合。
そして、もしそうならparent[v] != y
、私の質問は!processed[y] &&
必要かどうかです。
したがって、yがvの親ではなく、processed[y] == false
yが見つかった(そうでない場合は実行がelse if
一部に到達できない)が処理されていない場合、yはvの祖母以上である必要があります。これはバックエッジですが、問題は、まだ処理されていないので処理できます。
さて、もしもprocessed[y] == true
?この「if」は決して起こらず、この条件は決して真ではないと思います。
なんで?processed[y]
さて、本当であると仮定しましょう。これは、yを含むすべてのパスが処理され、それらのパスのすべての頂点も処理されたことを意味します。それで、これが事実である場合、「まだ処理が完了していない」頂点vはどのようにyに近づくことができますか?
dfsでは、処理された頂点に頂点が近づくことはないと思いますが、正しいですか?
したがって、処理された頂点を肉付けしない場合は、!processed[y]
常に真であるため、削除するだけで済みます。