DFS on a graph the non-recursive way - recursion

I'm working on an exercise and I'm kind of stuck, need some help. Suppose we have the following vertices and edges on a directed graph: AB, BC, AD, CD, DC, DE, CE, EB, AE depicted below
Trying to figure out how many "trips" exist from C to C, with no more than 3 edges. That would be two (2), C-D-C and C-E-B-C
So far I've managed to solve it by using DFS and recursion. I keep track of the depth (i.e. how many edges away from source) and when that becomes more that 3, the recursive function returns.
What I'm trying to do now is solve it without using recursion, that is, by using a stack, but I'm stuck! If I use something like the following (pseudo code):
s.create() <- create stack
s.push(nodeA)
depth = 0
while !s.empty
n = s.pop()
foreach (n.connectedVertices as c)
s.push(c)
depth++
Then I have no way to know which depth each vertex is supposed to be on. I've been thinking of using a stack of stacks somehow (saved for each depth?) but haven't figured that out yet.
Any help would be greatly appreciated.

You can do this by pushing pairs in stack .
the pair will contain (node , depth) .
Now initially push (node , 0) .
s.create()
s.push(nodeA , 0)
while !s.empty
cur_node , depth = s.pop()
if depth==3
continue // if depth = 3 then we don't need to push anything .
for each node connected with cur_node
s.push(node , depth + 1)
I hope you got the idea of how can we calculate answer .

Related

Find depth difference between two nodes in a tree without going all the way up to the root

I Came across a question I couldn't figure out.
Assume A binary tree, where each node has a pointer to its parent, and two children.
We receive input for r, p,q ( root, and two nodes from the tree) and we want to find the depth difference between p and q, Without Traversing all the way up to the root.
Limitations and Assumptions:
No memory usage (meaning no arrays, variables are ok)
Assume the nodes Lowest Common Ancestor isn't the root (and for simplicity let's assume the LCA is far from the root in Big-O notation Terms.
Just to clarify -
Basically, the question is how do we figure out the depth difference without going all the way up to the root, and without memory.
Thanks!
Basically, the question is how do we figure out the depth difference without going all the way up to the root...
It isn't saying that you cannot traverse all the way up to the root. It just says that the final outcome may not be the root.
First, define a function to determine the depth of a node (pseudo code):
function depthOf(r, p):
depth = 0
temp = p
while curr is not r:
depth++
temp = temp.parent
return depth
Simply call this function for both nodes, and take the difference.
As an additional feature, you can use this information to find the Lowest Common Ancestor:
Use the depth difference to walk up from the deepest node of the two up until you are at the same depth as the other. From then on walk upwards from both nodes in tandem, until you arrive at the same node from both sides:
function least(r, p, q)
diff = depthOf(r, p) - depthOf(r, q) # The answer
# In order to find least common ancestor, continue as follows:
while diff > 0: # p is deeper than q
p = p.parent
diff--
while diff < 0: # q is deeper than p
q = q.parent
diff++
while p is not q:
p = p.parent
q = q.parent
return p

Modified Shortest Path Algorithm (Dijkstra's)

So my problem is that I have a directed graph G with non-negative edge lengths and I wish to find the shortest path between two nodes u and v such that they only pass through one marked node in the graph.
If we did not have the condition involving the marked nodes this problem could easily be solved using Dijkstra's algorithm.
procedure dijkstra(G, l, s)
Input: Graph G = (V, E), directed or undirected;
positive edge lengths {le : e ∈ E}; vertex s ∈ V
Output: For all vertices u reachable from s, dist(u) is set to the distance from s to u.
for all u ∈ V :
dist(u) = ∞
prev(u) = nil
dist(s) = 0
H = makequeue(V ) (using dist-values as keys)
while H is not empty:
u = deletemin(H)
for all edges (u, v) ∈ E:
if dist(v) > dist(u) + l(u, v):
dist(v) = dist(u) + l(u, v)
prev(v) = u
decreasekey(H, v)
Additionally, to handle the condition I was considering adding a value which gave the current number of nodes in the current best path from s to u (this would be updated whenever dist(u) was updated). But this doesn't seem to work since the algorithm is not keeping track of all possible paths that we've seen with one or less nodes , but rather just the lowest distance path.
My question is am I on the right track and just need to modify the algorithm additonally? Or is there another algorithm that would accomplish this easier?
Also, this is for a homework problem so please do not post an entire solution, I'm just looking for guidance.
As you don't want the entire solution, I will give you some hints. Stop reading each paragraph and then try to solve the problem, I'll try to go from more general hints to more specific ones.
First, I don't think your current idea can solve the problem. So I will try to guide you to a different approach. It is a good idea to think of Dijkstra, but instead of modifying Dijkstra, consider transforming the graph so to achieve that running Dijkstra in your new graph solves the original problem.
How to remove the original restriction of the set P? Well, it is important that the graph is directed (or at least for my idea). Think of a way of transforming the graph so as to force that if you enter one node of P, you cannot enter another one of P again.
Last idea, without still giving the solution. Consider replicating the graph, maybe deleting some edges and connecting the nodes from the two copies in some way.

algorithm to test whether G contains an arborescence

An arborescence of a directed graph G is a rooted tree such that there is a directed path from the root to every other vertex in the graph. Give an efficient and correct algorithm to test whether G contains an arborescence, and its time complexity.
I could only think of running DFS/BFS from every node till in one of the DFS all the nodes are covered.
I thought of using min spanning tree algorithm, but that is also only for un-directed graphs
is there any other efficient algorithm for this ?
I found a follow up question which state there is a O(n+m) algorithm for the same, can anybody help what could be the solution ?
What you are exactly looking for is the so called Edmond's algorithm. The minimum spanning tree algorithms are not going to work on directed graphs but that is the idea. The MST problem became arborescence problem when the graph is directed and arborescence is what you have described above.
The naive complexity is O(EV) just like the Prim's algorithm for undirected MST problem but I am sure there are faster implementations of it.
For more information you can check the wiki page:
Edmonds Algorithm
First note that the definition for an arborescence of a directed graph given in the question above is a bit different from the one given in e.g. Wikipedia: your question's definition does not require that the path be unique, nor does it require that the original directed graph G be a weighted one. So a solution should be simpler than the one handled by Edmond's Algorithm.
How about the following: first part will be to find an adequate root. Once an adequate root is found, running a simple DFS on the graph G starting from that root should allow us to create the needed tree and we're done. So how can we find such a root?
Start by running DFS and "reduce" any cycle found to a single edge. Inside any cycle found, it won't matter which edge we use as any of them can reach any other. If a single edge is left after this reduction it means the entire graph is strongly connected and so any edge - including the only one left - can fit as root.
If more than one edge is left, go over all remaining edges, and find the ones having an in-degree of zero. If more than one is found - then we can't construct the needed tree - as they can't be reached from one another. If just a single edge is found here - that's our root edge.
Complexity is O(edges + vertices) in say an adjacency list representation of the graph.
I think this is much simpler than I thought. Something in the similar lines already mentioned at the beginning of the thread. So basically start the DFS traversal at any node in the graph using BFS and reach what ever you can and then the once you are done. Simply take the next unvisited vertex and do BFS traversal again and incase you encounter a node that is already processed means this is sub tree has already been processed and all the nodes reachable through this node will node be reached through another node hence make the current node as the parent of this new sub tree.
simply do a DFS traversal in which each edge is guaranteed to be visited only once. Do the following
edgeCb()
{
// Already processed and has no parent means this must a sub tree
if ( g->par[ y ] == -1 && g->prc[ y ] )
g->par[ y ] = x; // Connecting two disconnected BFS/DFS trees
return 1;
}
graphTraverseDfs( g, i )
{
// Parent of each vertex is being updated as and when it is visited.
}
main() {
.
.
for ( i = 0; i < g->nv; i++ )
if ( !g->vis[ i ] )
graphTraverseDfs( g, i );
.
.
}

Neo4J - Extracting graph as a list based on relationship strength

I have a typical friend of friend graph database i.e. a social network database. The requirement is to extract all the nodes as a list in such a way that the least connected nodes appear together in the list and the most connected nodes are placed further apart in the list.
Basically its asking a graph to be represented as a list and I'm not sure if we can really do that. For e.g. if A is related to B with strength 10, B is related to C with strength 80, A to C is 20
then how to place this in a list ?
A, B, C - no because then A is distant from C relatively more than B which is not the case
A, C, B - yes because A and B are less related that A,C and C,B.
With 3 nodes its very simple but with lot of nodes - is it possible to put them in a list based on relationship strength ?
Ok, I think this is maybe what you want. An inverse of the shortestPath traversal with weights. If not, tell me how the output should be.
http://console.neo4j.org/r/n8npue
MATCH p=(n)-[*]-(m) // search all paths
WHERE n <> m
AND ALL (x IN nodes(p) WHERE length([x2 IN nodes(p) WHERE x2=x])=1) // this filters simple paths
RETURN [n IN nodes(p)| n.name] AS names, // get the names out
reduce(acc=0, r IN relationships(p)| acc + r.Strength) AS totalStrength // calculate total strength produced by following this path
ORDER BY length(p) DESC , totalStrength ASC // get the max length (hopefully a full traversal), and the minimum strength
LIMIT 1
This is not going to be efficient for a large graph, but I think it's definitely doable--probably needs using the traversal/graphalgo API shortest path functionality if you need speed on a large graph.

advice needed with prolog cut?

in this task i have a Prolog database filled with e.g.
edge(1,0)
edge(2,0)
edge(1,3)
an edge signifies that two points are joined.
I am asked to write a function called reach(i,j,k) where i is the start point j is the end point and k is the number of steps you may use.
K is needed to stop the recursion looping e.g.
Suppose the only edge I’ve got goes from 1 to3,and I’m trying to get to 6. Then I can’t get from 1to6 in one go. so I’ll look for somewhere I can get to, and see if I can get from there to 6. The first place I can get to in one go is 3, so I’ll try to get from there to 6.
i have done this as so:
%% Can you get there in one step (need two rules because all links are
%% from smaller to greater, but we may need to get from greater to smaller.
reach1(I, J,_K) :-
edge(I, J).
reach1(I, J,_K) :-
edge(J, I).
%% Chhose somewhere you can get to in one step: can you get from there
%% to your target?
reach1(I,J,K) :-
K>1,
edge(I, B),
K1 is K-1,
reach1(B,J,K1).
reach1(I,J,K) :-
K>1,
edge(B, I),
K1 is K-1,
reach1(B,J,K1).
this works, however i am stuck with the second part in which we are asked not to use k but to use a "cut" to do this.
does anyone know how to do this or can give me some pointers?
The cut ensures that once a goal has been resolved in one way, it doesn't look for another way.
example:
reach(I, J,_K) :-
edge(I, J).
no cut - if for some reason Prolog backtracks, it will try to reach from I to J another way.
You might feel there's no point reaching this node another way if the simple edge works, and in that case you can do:
reach(I, J,_K) :-
edge(I, J),
!.
which "cuts" any alternative to this goal, but the one Prolog has found.

Resources