1
$\begingroup$

My task is to write a function that, given a source nodes of a graph, returns the number of sink nodes (nodes with no outgoing edges) it reaches. The only access I have is to retrieve the neighbors of a node (I don't have direct access to the graph itself). The solution involves recursion, where you sum the results for all of the source neighbors by calling the same function, but ignore the visited. However, you might be concerned about hitting the maximum recursion depth, so I considered using DFS with a stack to simulate recursion.

I solved the above efficiently with DFS.

My main task:

I have multiple such source nodes, and I struggle to avoid recalculating. For instance, given the edges (1,2), (1,3), (2,4), (3,4), (5,3), source node 1 will correctly return one sink node, but to calculate the result for source node 5, there seems to be no way to avoid recalculating.

A naive solution would be to keep a unique attribute for each node that stores all the sink nodes it reaches, and then the calculation for a node would be the union of its neighbors' attributes.

My approach is as follows:

For each source node, define an empty set of visited nodes and run DFS, summing the values of all the neighbors. If a neighbor has already been visited, it is ignored in the summation. The value of each sink node is 1. However, I ended up recalculating nodes.

You might think this approach won’t update all intermediate nodes correctly, and you'd be right.

So, I also considered adding an attribute to indicate whether a node was updated correctly. The issue with this approach is that if nodes 3 and 4 were correctly updated in a previous run, you might get an incorrect result (e.g., 1 node from above incorrectly showing it has two sink nodes).

So my question is: Is there any efficient approach that avoids recalculating?

$\endgroup$
1
  • $\begingroup$ @grebeard Thanks for clarification. $\endgroup$
    – Amit Dahan
    Commented Aug 14 at 6:12

1 Answer 1

1
$\begingroup$

Assuming you are asking about a directed graph:

As far as I am aware, I believe there is no solution that is significantly faster from running DFS once for each source (or, running DFS on the reverse graph once for each sink). There are theoretical results, but nothing that leads to any significant practical improvement.

See also https://cstheory.stackexchange.com/q/553/5038, https://cstheory.stackexchange.com/q/4258/5038, Number of descendants of each node in a DAG, Determining the number of reachable vertices from every vertex in a directed acyclic graph.

(In an undirected graph, the problem is trivial and uninteresting, as all sink nodes must be completely disconnected from all other nodes. Therefore, a source node reaches 1 sink node if it is itself a sink node, or 0 sink nodes otherwise.)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.