Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

graph - How to avoid reprocessing same edge twice in Depth First Search?

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.

like image 260
Jackson Tale Avatar asked Apr 05 '12 16:04

Jackson Tale


1 Answers

No, processed[y] == true could yield true.

Look at the following graph, and assume the following [feasible] DFS traversal:

v0,v1,v2

graph example

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

like image 55
amit Avatar answered Sep 23 '22 01:09

amit