I have questions about an optimal algorithm problem on a weighted graph. I am given an edgelist with weights, a list with savepoints, a starte- and end- node and the max distance for a step.
The output should be a list of savepoints, which are accessible in one step from starting- and end- node.
I thought of some kind of dijkstra's algorithm from each point of the list of savepoints.
I'm not sure if that's a good idea, since if I have many savepoints I calculate a lot of paths multiple times. Every idea/help is welcome!
Thank you very much in advance!
You have to have the condition that a weight cannot be negative, otherwise the problem becomes very intractable. Otherwise it's just a breadth first search, with marking the distance for every visited node. So you don't revisit a node is a previous move has visited it earlier at lower cost.
You keep a priority queue of all active nodes, so you are checking the lowest cost node each time. The priority queue is in fact the hardest part to get right. If you check the A* algorithm for my binary image library https://github.com/MalcolmMcLean/binaryimagelibrary you can take the priority queue for there. A* over a maze is very similar to shortest path over a graph, but you don't have a heuristic because you must have the exact shortest path, and instead of 4 / 8 edges per tile, you have nodes with arbitrary numbers of connections.
Related
In a graph with a bunch of normal nodes and a few special marked nodes, is there a common algorithm to find the closest marked node from a given starting position in the graph?
Or is the best way to do a BFS search to find the marked nodes and then doing Dijkstra's on each of the discovered marked nodes to see which one is the closest?
This depends on the graph, and your definition of "closest".
If you compute "closest" ignoring edge weights, or your graph has no edge weights, a simple breadth-first search (BFS) will suffice. The first node reached vía BFS is, by definition of BFS, the closest (or, if there are several closest nodes, tied for closeness). If you keep track of the number of expanded BFS levels, you can locate all closest nodes by reaching the end of the level instead of stopping as soon as you find the first marked node.
If you have edge weights, and need to use them in your computation, use Dijkstra instead. If the edges can have negative weights, and there happen to be any negative cycles, then you will need to instead use Bellman-Ford.
As mentioned by SaiBot, if the start node is always the same, and you will perform several queries with changing "marked" nodes, there are faster ways to do things. In particular, you can store in each node the "parent" found in a first full traversal, and the node's distance to the start node. When adding a new batch of k marked nodes, you would immediately know the closest to the start by looking at this distance for each marked node.
The fastest way would be to perform Dijkstra right away from your starting position (starting node). When "closeness" is defined as the number of edges that have to be traversed, you can just assign a weight of 1 to each edge. In case precomputation is allowed there will be faster ways to do it.
I am currently revising for one of my exams and have come accross this question,
"Show, step by step, the use of Dijkstra’s algorithm to find the shortest path from the vertex A to each other vertex in the graph. At each step the known and frontier sets should be clearly indicated."
I understand how to find the shortest path but I am usnsure of what a frontier set is?
Thank you!
There are many ways to formulate Dijkstra's algorithm, but the core idea behind most versions is to split the nodes into three groups:
Nodes where you already know the shortest path from the start point. This is initiallt just the start node and grows as the algorithm runs for longer and longer periods of time.
Nodes in the frontier. These are nodes adjacent to nodes in the first group, where you have a guess of the distance to the node but can't necessarily be sure that guess is correct. At each step in the algorithm, you choose the lowest-cost node in the frontier and move it to the group of nodes where you know the shortest path.
Unexplored nodes. These are all the remaining nodes.
If you implement Dijkstra's algorithm with a priority queue, then the frontier nodes are typically the ones in the priority queue. If you maintain a list of candidate distances to nodes and instead pick the cheapest one at each point, the frontier consists of all the nodes whose candidate distance isn't infinity.
I have a follow-up question on this:
Finding shortest path distances in a graph containing at most two negative edges
Ranveer's solution looks great, but it is not fast enough because I need O(|E| + |V|*log|V|) fast algorithm.
I guess Dukeling's solution works great. It makes sense and it operates in the same running time of Dijkstra's algorithm.
However, my goal is to find shortest path distances from a given node s to ALL the nodes in V.
If I apply Dukeling's algorithm by setting all the nodes in V as end vertex e, I will need to run it |V| - 1 times. Then, the running time will be O(|V||E| + |V^2|*log|V|).
Any help would be appreciated!
Dijkstra's algorithm, in its original form, finds all the shortest paths from a source node to all other nodes in the graph.
You have (at least) two options for your problem:
Use Bellman - Ford. It's not as slow as its big-oh would suggest, at least not necessarily. Make sure you implement it like you would a BF search: using a FIFO queue. This means you will insert a node into the queue every time the distance to it is updated, and only if it isn't already in the queue. Other optimizations are also possible, but this should already give you a fast algorithm in practice;
Use Dijkstra's, but modified similarly to Bellman - Ford: the default Dijkstra's never inserts a node twice into the priority queue. Make sure you reinsert nodes if you have updated the distance to them. This will deal with negative cost edges. It essentially makes the algorithm closer to the Bellman - Ford described above, but using a priority queue instead of a FIFO queue. This will also get you closer to your desired complexity.
I am working on a graph library.It has to have a function which finds the two nodes which are most separated i.e they maximum number of the minimum number of nodes required to traverse before reaching the target node from the source node.
One naive way would be to calculate the degree of separation from each node to all other node and repeat the same for every node.
The complexity of this turns out to be O(n^2).
Any better solution to this problem ?
Use Floyd-Warshall algorithm to find all pairs shortest path. Then iterate through results and find one with the longest path.
Without any assumptions on the graph, Floyd-Warshall is the way to go.
If your graph is sparse (i.e. it has a relatively few edges by node, or |E|<<|N|^2), then Johnson is likely to be faster.
With unit edge weight (which seems to be your case), a naïve approach by computing the furthest node (with BFS) for each node leads to O(|N|.|E|). This can probably be improved further, but I don't see a way right now.
There is a custom implementation of KSPA which needs to be re-written. The current implementation uses a modified Dijkstra's algorithm whose pseudocode is roughly explained below. It is commonly known as KSPA using edge-deletion strategy i think so. (i am a novice in graph-theory).
Step:-1. Calculate the shortest path between any given pair of nodes using the Dijkstra algorithm. k = 0 here.
Step:-2. Set k = 1
Step:-3. Extract all the edges from all the ‘k-1’ shortest path trees. Add the same to a linked list Edge_List.
Step:-4. Create a combination of ‘k’ edges from Edge_List to be deleted at once such that each edge belongs to a different SPT (Shortest Path Tree). This can be done by inspecting the ‘k’ value for each edge of the combination considered. The ‘k’ value has to be different for each of the edge of the chosen combination.
Step:-5. Delete the combination of edges chosen in the above step temporarily from the graph in memory.
Step:-6. Re-run Dijkstra for the same pair of nodes as in Step:-1.
Step:-7. Add the resulting path into a temporary list of paths. Paths_List.
Step:-8. Restore the deleted edges back into the graph.
Step:-9. Go to Step:-4 to get another combination of edges for deletion until all unique combinations are exhausted. This is nothing but choosing ‘r’ edges at a time among ‘n’ edges => nCr.
Step:-10. The ‘k+1’ th shortest path is = Minimum(Paths_List).
Step:-11. k = k + 1 Go to Step:-3, until k < N.
Step:-12. STOP
As i understand the algorithm, to get kth shortest path, ‘k-1’ SPTs are to be found between each source-destination pair and ‘k-1’ edges each from one SPT are to be deleted simultaneously for every combination.
Clearly this algorithm has combinatorial complexity and clogs the server on large graphs. People suggested me Eppstein's algorithm (http://www.ics.uci.edu/~eppstein/pubs/Epp-SJC-98.pdf). But this white paper cites a 'digraph' and I did not see a mention that it works only for digraphs. I just wanted to ask folks here if anyone has used this algorithm on an undirected graph?
If not, are there good algorithms (in terms of time-complexity) to implement KSPA on an undirected graph?
Thanks in advance,
Time complexity: O(K*(E*log(K)+V*log(V)))
Memory complexity of O(K*V) (+O(E) for storing the input).
We perform a modified Djikstra as follows:
For each node, instead of keeping the best currently-known cost of route from start-node. We keep the best K routes from start node
When updating a nodes' neighbours, we don't check if it improves the best currently known path (like Djikstra does), we check if it improves the worst of the K' best currently known path.
After we already processed the first of a nodes' K best routes, we don't need to find K best routes, but only have K-1 remaining, and after another one K-2. That's what I called K'.
For each node we will keep two priority queues for the K' best currently known path-lengths.
In one priority queue the shortest path is on top. We use this priority queue to determine which of the K' is best and will be used in the regular Djikstra's priority queues as the node's representative.
In the other priority queue the longest path is on top. We use this one to compare candidate paths to the worst of the K' paths.