Turning Recursive algorithm into breadth-first queue - ruby

So I am working with a "course". The course is full of coordinates. Each coordinate has attributes that allow movement(#left #right #up #down). The course is built upon a coordinate system so left would be x-1, right would be x+1, up would be y-1, and down would be y+1.
My goal is to get the shortest distance of each reachable coordinate.
Distance is defined by the number of moves from the start point (the start coordinate of the course that is provided in the parameters). So the distance from (0,0) to (1,2) would be 3. 1 right and 2 down
I've originally solved this problem using recursion:
Answer: Rather than go through each one as far as as possible in depth, use an array to go through each of the paths within each difference at a time

Think of your problem as a undirected graph with the nodes being the coordinates, where each pair of (distinct) nodes [x0,y0] and [x1,y1] is "adjacent" if:
[x0-x1].abs <= 1 && [y0-y1].abs <= 1
Two nodes are connected by an undirected link if they are adjacent, in which case the length of that link is 1. If two nodes are connected by a path of nodes and links, the distance between them equals the sum of the lengths of the links on the path (i.e., the number of links in the path).
You can find the shortest distance between all pairs of coordinates by employing an algorithm that computes shortest paths between all pairs of nodes in an undirected graph, such as the Floyd-Warshall algorithm (which also works for directed graphs).
Floyd-Warshall treats non-adjacent pairs of nodes as being connected by a link of infinite length (which may be implemented as a suitably large number). If the length of the shortest path between a given pair of nodes is found to be "infinite", you know the nodes are not connected (i.e., there is no path between the coordinates).

Related

Algorithm to find any two nodes with distance of at least half the (undirected) graph's diameter

I have to give an algorithm as follows:
Given an undirected connected graph G, give an algorithm that finds two nodes x,y such that their distance is at least half the diameter of the Graph. Prove any claim.
I'm assuming I have to run a BFS from any arbitrary node and find its furthest node to find the diameter. Then find two of the explored nodes whose distance is bigger than half the diameter.
But I doubt this is the optimal and asked for solution. Is there any other way that when running the BFS to find the diameter, to simultaneously find these two required nodes? So that the complexity remains polynomial.
Any guidance or hint would be appreciated!
The diameter (lets call it D) of a graph is the largest distance (= minimal number of hops) between any of its nodes.
Choose any node and perform BFS, while retaining, for each node, the number of hops from your initial node. This takes O(V), since you will visit all nodes exactly once. Note that this number of hops is also the shortest distance to v from the root - which I will refer to as d(root, v).
Now, take the leaf z that has the largest number of hops from your root. Congratulations, d(root, z) >= D/2, because
Lemma: for any node x in a connected graph of diameter D, there must exist a node y that is at least D/2 far away.
Proof: If this were not so, then there would be some node x so that, for all y, d(x,y) = D/2 - k <= D/2 (with k>=1). But then, by passing through x, we could find paths from any node to all others in at most 2 * (D/2 - k) = D - 2k - and therefore, the graph's diameter could not be D, but D - 2k.
Thats actually the tricky one, but I think I got it. Interesting thing is that your partially wrong solution put me on the right way.
Lets just copy here few definitions:
Distance between two vertices in a graph is the number of edges in a shortest path
The eccentricity of a vertex v is the greatest distance between v and any other vertex
The diameter d of a graph is the maximum eccentricity of any vertex in the graph. That is, d is the greatest distance between any pair of vertices
The real issue would be to actually find the diameter, its not an easy task. To find diameter you cannot just choose any node and run BFS - in such case you just find node that has highest distance from that node (the eccentricity), but it is not diameter. To actually find diameter you would have to run BFS (=find eccentricity) from every single node and the highest distance you got is diameter (there are some better alghoritms, but as I said - its not simple task).
However! You dont have to know the diameter at all. If you actually run BFS from random node and you find the node with highest distance (eccentricity) - thats the solution to your alghorithm. x would be your starting node and y would be the node with highest distance.
Why? If you imagine super simple graph like this
You can see that the diameter is between nodes 1 and nodes 4. So no matter from which point you run the BFS, that point has to be either in a middle (which means it will have half the diameter) or not in the middle and then the node with highest distance must have even higher distance than half the diameter.
Even more complex graphs do not change the fact
If you choose 6 or 7, its not exactly in diameter path (because the highest distance is between 1-2-3-4-5), but it means that you get even higher distance, which is fine for your task.
Result: Run the BFS from random node, when it ends, take node with highest distance from the starting node (=find eccentricity and remember the furthest node) and the starting and "ending" nodes are (x,y)

Traversing a graph and meeting a certain criteria?

I want to find the path between two vertices of a graph grid (A x B size, with 1x1 cells) (a1, b1) and (a2, b2) but with additional criterion of avoiding some n forbidden nodes (x1, y1), (x2, y2) as far away as possible from any one node to reach the destination. This means for all potential paths, the closest distance to any forbidden node should be the largest. The node positions are integers but the distance away from the nodes can be float numbers.
I would think the shortest path algorithms like Dijkstra's probably wouldn't matter a lot since the shortest path could end up traversing one of the n forbidden nodes. But then how can I factor in the "furthest distance away" from the nodes factor? My thoughts:
I could try to average positions of the forbidden nodes, but I have managed to come up with one counter example that this might end up traversing one of the nodes
The alternative way is to simply compute all possible paths and find the one with the furthest distance from any one forbidden node. This might mean using some dynamic programming approach.
We can also tabulate the min distance from any one forbidden nodes at every node in the graph, and choose the path that gives the greatest distance at each step.
Other thoughts: might have to use disjoint sets and MSTs?
My potential solutions seem to incur very high time complexity and I thought this kind of problem should be quite common (people probably have thought of this before). Is there a standard practice or way to approach this kind of problems optimally?
Pick a distance D and remove from the graph all nodes within distance D of the forbidden nodes. Find out if the source and destination are still connected. Use binary chop to find the largest possible D still leaving the source and destination connected. The path from source to destination on this graph is the path you want.

Shortest paths with 2 constraints (Weight and Colour)

Input: We have a directed graph G=(V,E) and each edge has a weight and a colour {red,green}. We are also given a starting node s.Problem/Algorithm: Can we find for all u edges of G, the shortest paths s-u with at most k red edges ? First approach: We save for each node the shortest path with 0,1...k red edges. We modify Dijkstra's algorithm and depending on the colour of the edges we are looking into, we update the distances respectively. This approach fails due to its complexity. Second approach: We make k copies of G graph (G1,G2 ...Gk+1). In order to utilise the k red edges constraint, while we are searching for shortest paths with Dijkstra, every time we "meet" a red edge {ui,vi} in Gi, we connect ui with vi+1 in Gi+1. Because Gk+1 doesn't have any red edges, we can only reach Gk+1 with at most k edges.But it fails. For example with k=2 if a 2 red edges shortest path is found to X node then will not take into consideration a heavier path with less red edges which could lead to an undiscovered node. (If i had enough reputation i could post an image as example). Any ideas ?
I think your approaches are actually equivalent, provided that for approach #1, you record only the shortest distance to each node for each number of red edges used -- you don't need to record the entire path (just as you don't need to record it for ordinary Dijkstra on an ordinary shortest path problem)
Also this approach is sound. In particular, your reasoning that approach #2 is faulty is itself wrong: for any node X in the original graph, there is no single corresponding node X in the new graph; instead there are separate vertices for each number of red edges used. So the two paths "to X" you are considering are not actually to the same node: one is to (X, 2 red edges used) and one is to e.g. (X, 1 red edge used). Then you can use a single Dijkstra run to calculate shortest paths to all k+1 copies of every vertex (i.e. to the vertices (v, i red edges used) for each 0 <= i <= k and for each v in V(G)), and return the lowest. (I'm assuming here that when you wrote "Can we find for all u edges of G, the shortest paths s-u", you meant "for all nodes u of G, the shortest paths s-u".)
Finally, you need to make sure that for any red edge {u, v} in G, you delete the corresponding edge {ui, vi} for all Gi (as well as add in the edge {ui, vi+1}). You probably intended this, but you weren't explicit about it.

finding whether a path of a specific length exists in an acyclic graph

In an acyclic graph, I am trying to find out whether or not a path of length L exists between two given nodes. My questions is, what is the best and the simplest Algorithm to use in this case.
Note that the graph has a maximum of 50 nodes and 100 edges.
I have tried to find all the paths using DFS and then to check if that path exists between the two nodes but I got the answer "Time Limit Exceeded" from the online judge.
I also used the Uniform Cost Search Algorithm but I also a got a negative response.
I need a more efficient way for solving such problem. Thank you.
I don't know if it will be faster then a DFS approach - but it will give a feasible solution:
Represent the graph as a matrix A, and calculate A^L - a path of length L between i and j exists if and only if A[i][j] != 0
Also, regarding DFS solution: You do not need to find all paths in the DFS - you should limit yourself to paths of length <= L, and by this trim some searches, once the length have exceeded the needed length. You could also escape the search once a path of length L is reaching the target.
Another possible optimization could be bi-directional search.
Find all vertices which have path of length L/2 from the source to
them.
Next, find all vertices which have paths of length L/2 from them
to the target (DFS on the reverse graph)
Then, check if there is a vertex that is common to both sets, if
there is - you got a path of length L from the source to the target.
Since the graph is acyclic you can order vertices topologicaly.
Let's name starting vertex A and finish vertex B.
Now the core algorithm starts:
For each vertex count all possible distances from A to this vertex. At start there is
one path from A to A with length zero.
Then take vertices in topological order.
When you pick vertex x: Look at each predecessor and update possible distances here.
This should run in O(N^3) time.
You can use a modified Dijkstra algorithm where instead of saving for every vertex the minimum distance to the origin, you save all the possible distances less or equal to the one desired.
I believe that you can use the following algorithm to find the longest path in a tree. This assumes that your graph is connected, if it is not you would need to rerun this on each connected component:
Pick an arbitrary node, A.
Do a BFS (or DFS) from A to find the node in the tree farthest from A, call this node B.
Do a BFS (or DFS) from B to find the node in the tree farthest from B, call this node C.
The path from B to C is the longest path in the tree (possibly tied for longest).
Obviously if this path is longer than L then you can shorten it to find a path of length L.

Using a minimum spanning tree algorithm

Suppose I have a weighted non-directed graph G = (V,E). Each vertex has a list of elements.
We start in a vertex root and start looking for all occurances of elements with a value x. We wish to travel the least amount of distance (in terms of edge weight) to uncover all occurances of elements with value x.
The way I think of it, a MST will contain all vertices (and hence all vertices that satisfy our condition). Therefore the algorithm to uncover all occurances can just be done by finding the shortest path from root to all other vertices (this will be done on the MST of course).
Edit :
As Louis pointed out, the MST will not work in all cases if the root is chosen arbitrarily. However, to make things clear, the root is part of the input and therefore there will be one and only one MST possible (given that the edges have distinct weights). This spanning tree will indeed have all minimum-cost paths to all other vertices in the graph starting from the root.
I don't think this will work. Consider the following example:
x
|
3
|
y--3--root
| /
5 3
| /
| /
x
The minimum spanning tree contains all three edges with weight 3, but this is clearly not the optimum solution.
If I understand the problem correctly, you want to find the minimum-weight tree in the graph which includes all vertices labeled x. (That is, the correct answer would have total weight 8, and would be the two edges drawn vertically in this drawing.) But this does not include your arbitrarily selected root at all.
I am pretty confident that the following variation on Prim's algorithm would work. Not sure if it's optimal, though.
Let's say the label we are looking for is called L.
Use an all-pairs shortest path algorithm to compute d(v, w) for all v, w.
Pick some node labeled L; call this the root. (We can be sure that this will be in the result tree, since we are including all nodes labeled L.)
Initialize a priority queue with the root initialized to 0. (The priority queue will consist of vertices labeled L, and their minimum distance from any node in the tree, including vertices not labeled L.)
While the priority queue is nonempty, do the following:
Pick out the top vertex in the queue; call it v, and its distance from the tree d.
For each vertex w on the path from v to the tree, v inclusive, find the nearest L-labeled node x to w, and add x to the priority queue, or update its priority. Add w to the tree.
The answer is no, if I'm understanding correctly. Finding the minimum spanning tree will contain all vertices V, but you only want to find the vertices with value x. Thus, your MST result may have unneeded vertices adding extra path length and therefore be sub-optimal.
An example has been given where the MST M1 from Root differs from an MST M2 containing all x nodes but not containing Root.
Here's an example where Root is in both MST's: Let graph G contain nodes R,S,T,U,V (R=Root), and a clockwise path R-S-T-U-V-R, with edge weights 1,1,3,2,2 going clockwise, and x at R, S, T, U. The first MST, M1, will have subtrees S-T and V-U below R, with cost 6 = 2+4, and cost-3 edge T-U not included in M1. But M2 has subtree S-T-U (only) below R, at cost 5.
Negative. If the idea is to find for every node that contains 'x' a separate path from root to it, and minimize the total cost of the paths, then you can just use simple shortest-path calculation separately for every node starting from the root, and put the paths together.
Some of those shortest paths will not be in the minimum spanning tree, so if this is your goal, the MST solution does not work. MST optimizes the cost of the tree, not the sum of costs of paths from root to the nodes.
If your idea is to find one path that starts from root and traverses through all nodes that contain 'x', then this is the traveling salesman problem and it is an NP-complete optimization problem, i.e. very hard.

Resources