The Algorithm Design Manual describes BFS and DFS quite well. The code for dfs in the book has a problem when deciding whether or not to avoid double processing edges. I found the Errata and applied the errata to the code, but still I think the refined code has a problem of checking double processing edges.
I paste the refined code as follows:
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;
}
The place where I think there is a problem is marked via ** **.
So the questionable place is one of the conditions. Let's assume it is undirected graph, so we can just ignore the condition of (g->directed)
.
Ok, let's focus on parent[v] != y
first. if parent[v] == y
, of course, we don't need to process edge v->y again because y->v is already processed once when processing vertex y.
And if parent[v] != y
, my question is whether !processed[y] &&
is necessary or not.
So, if y is not v's parent, and processed[y] == false
which means y has been found (otherwise the execution can't reach else if
part) but not been processed, so y must be a grandma or above of v. This is a back edge, but no problem, we can process it as it hasn't been processed yet.
Now what if processed[y] == true
? I think this "if" will never happen and this condition will never be true.
Why? Ok, let's assume processed[y]
can be true. This means that all paths which include y have been processed and also all vertexes in those paths have been processed, right? So if this is a case, how can a "not yet finished processing" vertex v approach y?
I think in dfs, no vertex will ever approach a processed vertex, am I right?
So if we never will meat a processed vertex, we can just remove !processed[y]
as it will be always true.
No, processed[y] == true
could yield true.
Look at the following graph, and assume the following [feasible] DFS traversal:
v0,v1,v2
v0
starts, and then recursively invoke dfs(v1)
after processing (v0,v1)
. Now, v1
processes (v1,v2)
and recursively invoke dfs(v2)
. v2
sees that v0
is discovered and go to the else if
statement, and sees that (v0,v2)
was not processed and parent[v2] != v0
[v2
was discovered via v1
].
Now, when we go back from the recursion we reach back v0
, and when we check the next "son" - it is v2
. v2
was already discovered, so we go to else if
, and v2
is not the parent of v0
, so without the !processed[y]
part, we would have processed (v0,v2)
twice.
The only thing that prevent that from hapenning is the fact that processed[y] == true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With