Am I thinking in the right way about this Negative weights using Dijkstra's Algorithm graph? - algorithm

I've been trying to wrap my head around why Dijkstra's algorithm doesn't work on negative weighted graphs and I understand all examples that has a further node pointing back to a node that has been fully explored. But this examples does my head in;
Would I be correct in thinking that; first A is explored. A->B will be 1 and A->C will be 100. Then B is explored and sets B->D to 2. Then D is explored because currently it has the shortest path back to the source (i.e. At the top of the priority queue)?
Would I be correct in saying that if B->D was 100, C would've been explored first (since A->D is 101)?
The one thing that people didn't really mention in every explanation was that a node has been explored/visited, it can't be updated anymore because Dijkstra works on a priority queue. I just find it hard to wrap my head around why D is visited before C in this case.

It's straightforward: when a node using Djikstra's algorithm is explored/visited/closed this means that you have found the shortest path to that node, therefore this node does not need to be reexplored or revisited, you already know the shortest path to the node.
For instance, when you select D to be explored there are two paths in the PQ:
A-B-D with cost 2
A-C with cost 100
and the path with least cost is selected. Then, it's obvious that if arc costs are always positive there's no way that you can find a shortest path to D going through A-C. The shortest path to D has been found and the node is closed.
All this reasoning is however not true when negative arc costs are allowed, so that's why Djikstra's algorithm does not work for them.

I think Dijkstra algorithm that you are describing operates only on positive weight functions. In particular Dijkstra algorithm gives a valid metric space structure on every weighted (positively) graph. On the other hand this seems to be not the case for arbitrary weighted graphs. Take for instance the graph with two nodes A and B and one edge between them with weight -5. In this case this will not give a distance between A and B. So what you describing, I think would fall into some sort of modified Dijkstra model and the interpretation of going from one node to another can no longer be interpreted as distance between the nodes.

Related

Find Two vertices with lowest path weight

I am trying to solve this question but got stuck.
Need some help,Thanks.
Given an undirected Connected graph G with non-negative values at edges.
Let A be a subgroup of V(G), where V(G) is the group of vertices in G.
-Find a pair of vertices (a,b) that belongs to A, such that the weight of the shortest path between them in G is minimal, in O((E+V)*log(v)))
I got the idea of using Dijkstra's algorithm in each node which will give me O(V*((E+V)logv))),which is too much.
So thought about connecting the vertices in A somehow,did'nt find any useful way.
Also tried changing the way Dijkstra's algorithm work,But it get's to hard to prove with no improvment in time complexity.
Note that if the optimal pair is (a, b), then from every node u in the optimal path, a and b are the closest two nodes in A.
I believe we should extend Dijkstra's algorithm in the following manners:
Start with all nodes in A, instead of a single source_node.
For each node, don't just remember the shortest_distance and the previous_node, but also the closest_source_node to remember which node in A gave the shortest distance.
Also, for each node, remember the second_shortest_distance, the second_closest_source_node, and previous_for_second_closest_source_node (shorter name suggestions are welcome). Make sure that second_closest_source_node is never the closest_source_node. Also, think carefully about how you update these variables, the optimal path for a node can become part of the second best path for it's neighbour.
Visit the entire graph, don't just stop at the first node whose closest_source and second_closest_source are found.
Once the entire graph is covered, search for the node whose shortest_distance + second_shortest_distance is smallest.

Dijkstra with Parallel edges and self-loop

If I have a weighted undirected Graph with no negative weights, but can contain multiple edges between vertex and self-loops, Can I run Dijkstra algorithm without problem to find the minimum path between a source and a destination or exists a counterexample?
My guess is that there is not problem, but I want to be sure.
If you're going to run Dijkstra's algorithm without making any changes to he graph, there's a chance that you'll not get the shortest path between source and destination.
For example, consider S and O. Now, finding the shortest path really depends on which edge is being being traversed when you want to push O to the queue. If your code picks edge with weight 1, you're fine. But if your code picks the edge with weight 8, then your algorithm is going to give you the wrong answer.
This means that the algorithm's correctness is now dependent on the order of edges entered in the adjacency list of the source node.
You can trivially transform your graph to one without single-edge loops and parallel edges.
With single-edge loops you need to check whether their weight is negative or non-negative. If the weight is negative, there obviously is no shortest path, as you can keep spinning in place and reduce your path length beyond any limit. If however the weight is positive, you can throw that edge away, as no shortest path can go through that edge.
A zero-weight edge would create a similar problem than any zero-weight loop: there will be not one but an infinite number of shortest paths, going through the same loop over and over again. In these cases the sensible thing is again to remove the edge from the graph.
Out of the parallel edges you can throw away all but the one with the lowest weight. The reasoning for this is equally simple: if there was a shortest path going through an edge A that has a parallel edge B with lower weight, you could construct an even shorter path by simply replacing A with B. Therefore no shortest path can go through A.
It just needs a minor variation. If there are multiple edges directed from u to v and each edge has a different weight, you can either:
Pick the weight with least edge for relaxation; or
Run relaxation for each edge.
Both of the above will have the same complexity although the constant factors in #2 will have higher values.
In any case you'll need to make sure that you evaluate all edges between u and v before moving to the next adjacent node of u.
I don't think it will create any kind of problem.As the dijkstra algorithm will use priority queue ,so offcourse minimum value will get update first.

Graphs - How to count the minimum number of "broken roads" necessary to go from v1 to v2?

Given a graph (undirected, no-weighted and all vertices are connected to eachother), I need to find the minimum number of "bad edges" I must visit to go from A to B. For example, if there's a graph with 5 vertices and the bad edges are: (0,1), (0,2), (0,3) and (0,4), to go from 0 to 4 I'll need to visit at least 1 bad edge. It could be straightfoward from 0 to 4 or from 0 to 1 and then 1 to 4. The length of the path doesn't matter at all. I'm trying a modified BFS to do the job but I'm not quite sure if this is the right way. My modification is instead of using a queue, use a list and when I find a bad edge, I put it into the back of the list, so I'll only visit this edge if really necessary, but found out that it won't minimize the number of bad edges. Any advices?
While it can indeed be solved by weighted shortest path, there is actually a more efficient (in terms of run time solutions).
First, define an auxillary graph G'=(V,E') where e is in E' iff e is "good". This step is linear in the size of the graph.
Now, you can find connected components in G' using DFS or BFS in O(|V|+|E|).
Next, all you have to do is "collapse" all nodes to a single node that represent them (this is also linear time), and add the "bad edges" (note that there is never a "good edge" that connects between two components, or they would have been in the same component).
Now, you can run BFS on the new graph, and the length of the path is the minimal number of nodes needed.
While this is significantly more complex to implement than a simple weighted shortest path, this solution offers O(|V|+|E|) (which in your graph is O(|E|)) run time, compared to O(|E|log|V|) of weighted shortest path.

Can I use Dijkstra's shortest path algorithm in my graph?

I have a directed graph that has all non-negative edges except the edge(s) that leave the source (S). There are no edges from any other vertices to the source. To find the shortest distance from source (S) to a vertex (T) in the graph, can I use Dijkstra's shortest path algorithm even though the edges leaving the source is negative?
Assuming only source-adjecent edges can have negative weights and there is no path back to the source from any of the source-adjecent nodes (as mentioned in the comment), you can just add a constant C onto all edges leaving the source to make them all non-negative. Then subtract C from the final result.
On a more general note, Dijkstra can be used to solve shortest-path in any graph with negative edge weights (but no negative cycles) after applying Johnson's reweighting algorithm (which is essentially Bellman-Ford, but needs to be performed only once).
Yes, you can use Dijkstra on that type of directed graph.
If you use already finished alghoritm for Dijsktra and it cannot use negative values, it can be good practise to find the lowest negative edge and add that number to all starting edges, therefore there is no-negative number at all. You substract that number after finishing.
If you code it yourself (which is acutally pretty easy and I recommend it to you), you almost does not change anything, just start with lowest value (as usual for Dijkstra) and allow it, that lowest value can be negative. It will work in your case.
The reason you generally can't use Dijkstra's algorithm for (directed) graphs with negative links is that Dijkstra's algorithm is greedy. It assumes that once you pick a vertex with minimum distance, there is no way it can later be reached by a smaller paths.
In your particular graph, after the very first step, you traverse all possible negative edges and Dijkstra's assumption actually holds from now on. Regardless of the fact that those vertices directly connected to start now have negative values, once you identify which has the minimum distance, it can never be reached again with a smaller distance (since all edges you would traverse from this point on would have a positive distance).
If you think about the conditions that dijkstra's algorithm puts upon the edges for the algorithm to work it is only that they are never decreasing after initialisation.
Thus, it actually doesn't matter if the first step is negative as from those several points onwards the function is constantly increasing and thus the correct output will be found (provided there is no way to get back to the start square.).

Finding shortest path distances from a given node s to ALL the nodes in V in a graph with two negative edges

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.

Resources