0

I don't understand for potential cyclic graph traversals, why for is there a connection between source and destination node in the graph:

i) DFS, if a node is visited, we return false

ii) BFS, if a node is visited, we continue (in the loop)

example code (from https://structy.net/problems/undirected-path):

const undirectedPath = (edges, nodeA, nodeB) => {
  const graph = buildGraph(edges);
  return hasPath(graph, nodeA, nodeB, new Set());
}

// BFS
const hasPath = (graph, src, dst, visited) => {
  const queue = [src];
  
  while(queue.length > 0){
    const current = queue.shift();
    if(current === dst) return true;
    // if it's DFS, do not "continue", instead "return false" - why?
    if(visited.has(current)) continue;
    visited.add(current);
    for(let neighbor of graph[current]){
      queue.push(neighbor);
    }
  }
  return false;
}

const buildGraph = (edges) => {
  const graph = {}; 
  for(let edge of edges){
    const[a, b] = edge;
    if(!(a in graph)) graph [a] = [];
    if(!(b in graph)) graph [b] = [];
    graph[a].push(b);
    graph[b].push(a);
  }
  return graph;
}

const edges = [
  ['i', 'j'],
  ['k', 'i'],
  ['m', 'k'],
  ['k', 'l'],
  ['o', 'n']
];

undirectedPath(edges, 'j', 'm'); // -> true
Nelson Mak
  • 73
  • 5
  • Simulate either algo on a piece of paper using various graphs. In particular, use graphs with loops, not just simple trees. – Ulrich Eckhardt Dec 22 '21 at 19:06
  • When I draw it out, it seems to be for DFS, we should be using continue as well. Because the graph can be cyclic, potentially, we may be choosing a node we already searched first on the stack but that doesn't mean we should return false, it should just mean we ignore that path. – Nelson Mak Dec 22 '21 at 19:24
  • Well, do whatever works for you then! Apart from that, it's hard to reason code I can't see. Since you obviously didn't write the code, include a source attribution. That could also enable you to find updates/errata that might reveal important info. Please, as a new user, also take the [tour] and read [ask]. – Ulrich Eckhardt Dec 22 '21 at 19:59
  • I've edited my body with code. Do you see where my question is, for DFS, we return false if the Set has the current node, but for BFS, we simply continue (to skip the iteration). – Nelson Mak Dec 22 '21 at 22:02

1 Answers1

0

Consider a simple graph with two nodes:

  • A (the start)
  • B (the target)

There are two edges as well:

  • A->A
  • A->B

In your DFS approach, you have following steps

  • pop a current node off the stack, which gives you A
  • it's not the destination and wasn't visited, so you add it to the list of visited nodes
  • you now add the neighbours to the stack, which are A and B
  • next iteration, you pop another current node off the stack, which gives you A again
  • it was already visited, so you return false, even though a path exists

In short, your algorithm is faulty. Note that this doesn't even require the special case of an edge looping in on itself. All it takes is a loop that is evaluated before reaching the target. Also, if by chance the neighbor B was checked first, you would have gotten a correct result.

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55