I read the Bellman Ford Algorithm. What I couldn't understand is why is there a loop which runs for |V|-1 times (the upper loop in the following segment).
for ( i = 1; i <= V-1; i++)
{
for (j = 0; j < E; j++)
{
int u = graph->edge[j].src;
int v = graph->edge[j].dest;
int weight = graph->edge[j].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
{
dist[v] = dist[u] + weight;
}
}
I went through several tutorials. All are saying the same thing that There can be maximum |V| – 1 edges in any simple path, that is why the outer loop runs |v| – 1 times. The idea is, assuming that there is no negative weight cycle, if we have calculated shortest paths with at most i edges, then an iteration over all edges guarantees to give shortest path with at-most (i+1) edges.
So, when i=1, the distances I calculated after the relaxation method, are those the shortest distances from the source ?
Please explain this...
Bellman--Ford has two relevant invariants that hold for all vertices u.
There exists a path from the source to u of length dist[u] (unless dist[u] is INT_MAX).
After i iterations of the outer loop, for all paths from the source to u with i or fewer edges, the length of that path is no less than dist[u].
After V-1 iterations, the second invariant implies that no simple path from the source to u is shorter than dist[u]. The first hence implies that the path that we found is shortest.
Bellman ford vs Dijkstra
Bellman also work for negative weighted graph while Dijkstra work only for positive weighted graph.
Bellman has TC O(V*E) which is greater than the TC of Dijkstra i.e. O(V+E).
Steps of Bellman ford:-
Firstly we initialize an distance array with very large default value.
the array value of source is set to 0.
First try to find the shortest path in first iteration.
Now, again traverse all node and try to do the same as we did in 3rd step if we again we find new shortest path then negative cycle is present.
The idea of step 4 is, step 3 guarantees the shortest distances if the graph doesn’t contain a negative weight cycle. If we iterate through all edges one more time and get a shorter path for any vertex, then there is a negative weight cycle.
Related
I have a problem of finding a shortest path in positively weighted Directed Acyclic Graph, but with the restriction of maximum number of N steps(edges in the path). It is assumed that the path exists. Additional property of the graph is that if the edge (i, j) is in the graph, then any edge (i, k) is also in the graph for i < k < j. I'm only interested in shortest path between start and end of the graph (after topological sorting).
I know that there is an efficient algorithm for the shortest path in Directed Acyclic Graph in O(V+E) but it doesn't account for the steps limit. I can't think of any way to make it O((V+E)*N), but this would be ideal performance, as it should be good enough to handle graphs of 1000 nodes and 100 steps.
For example consider the following
graph.
The problem is to find the shortest path using at most k=3 steps (edges). The answer is 6 (path 1->4->5->6).
It is actually O(N + M) where N is the number of vertices and M is the number of edges.
You can find more information here: http://www.geeksforgeeks.org/shortest-path-for-directed-acyclic-graphs/
Finding the path (I'm using the code from geeksforgeeks):
Instead of int dist[V] use pair<int, int> dist[V]. Initially dist[S] = {0, -1}. So in this condition if (dist[i->getV()].first > dist[u].first + i->getWeight()) you need to set parent as dist[i->getV()] = {dist[u].first + i->getWeight(), u}.
Then use this recursive code to restore the path:
void restore(int v) {
if(dist[v].second == -1) return;
else answer.push_back(v);
if(v == START_POINT) return;
restore(dist[v].second);
}
Call it with restore(FINAL_POINT)
The algorithm is as follows:
The algorithm starts by topologically sorting the dag (see Section 22.4) to impose a linear ordering on the vertices. If the dag contains a path from vertex u to vertex v, then u precedes v in the topological sort. We make just one pass over the vertices in the topologically sorted order. As we process each vertex, we relax each edge that leaves the vertex.
Can somebody tell me the intuition behind it? And using that intuition please tell how do we find longest path just be negating the edge weights and running the algorithm
We cannot use Dijkstra's algorithm as edges are allowed to have negative weights.
Finding the shortest path to a vertex is easy if you already know the shortest paths to all the vertices that can precede it. Finding the longest path to a vertex in DAG is easy if you already know the longest path to all the vertices that can precede it.
Processing the vertices in topological order ensures that by the time you get to a vertex, you've already processed all the vertices that can precede it.
Dijkstra's algorithm is necessary for graphs that can contain cycles, because they can't be topologically sorted.
Your question is related to single-source shortest-path problem (SSSP) in DAG.
Topological sorting of a graph represents a linear ordering of the graph. It is allowed to process all vertices in topological order (from left to right), and all shortest paths will be found using relaxation property. Running time of the algorithm is O(|V| + |E|), where V is a set of vertices, E is a set of edges.
If you want to find the longest path (or the critical path) there are the next variants:
First way is to negate the edge weights. The path with the smallest negative value will give the longest path (but for algorithm it will still the smallest path). We can do it because topological sorting may work with negative edge weights.
Second way is to change the relaxation step:
1. Cost of each vertex is initialized to negative infinity
2. Change the relaxation step:
if d(v) < d(u) + w
then d(v) = d(u) + w
else d(v) is remains unchanged
where d - the distance;
u, v - vertices;
w - weight on edge (u, v).
In general case for solving SSSP problem there are Dijkstra's and Bellman-Ford algorithm. The main difference consists in the fact that Bellman-Ford algorithm computes SSSP for any weights in the graph and can detect negative weight cycles in the graph, but Dijkstra's algorithm can work with positive weights.
For more details see Shortest Paths.
Topological sort ensures that we are picking up nodes that come first while travelling from the source, this, in turn, will ensure that every node will have at least one condition that it can be reached from the source.
for (int i = 0; i < N; i++)
if (visited[i] == false)
topologicalSortUtil(i, visited, stack, adj);
for (int i = 0; i < N; i++)
dist[i] = Integer.MAX_VALUE;
dist[s] = 0;
while (stack.empty() == false)
{
int node = (int)stack.pop();
if (dist[node] != Integer.MAX_VALUE)
{
enter code here for(Pair it: adj.get(node)) {
if(dist[node] + it.getWeight() < dist[it.getV()]) {
dist[it.getV()] = dist[node] + it.getWeight();
}
}
}
}
As we are setting dist[src] = 0, it will start from there, the condition dis[node] != infinity will not let any other node than src enter that condition first. Because of topological sort notes coming before src will be discarded.
I need help to finding the number of all the shortest paths between two nodes in an directed unweighted graph.
I am able to find one of the shortest paths using BFS algorithm, but i dont know how to find all the shortest paths.
Any idea of the algorithm / pseudocode I could use?
Thanks!!
You can do it by remembering how many paths are leading to each node, and when discovering a new node - summarize that number.
For simplicity, let's assume you have regular BFS algorithm, that whenever you use an edge (u,v), calls visit(u,v,k), where:
u - the source node of the edge
v - the target node of the edge
k - the distance from the original source to u
In addition to this, assume you have a mapping d:(vertex,distance)->#paths.
This is basically a map (or 2D matrix) that it's key is a pair of vertex and an integer - distance, and its value is the number of shortest paths leading from the source, to that vertex, with distance k.
It is easy to see that for each vertex v:
d[v,k] = sum { d[u,k-1] | for all edges (u,v) }
d[source,0] = 0
And now, you can easily find the number of shortest paths of length k leading to each node.
Optimization:
You can see that "number of shortest paths of length k" is redundant, you actually need only one value of k for each vertex. This requires some book-keeping, but saves you some space.
Good luck!
The first idea that come to my mind is the next:
Let's name start vertex as s and end vertex as e.
We can store two arrays: D and Q. D[i] is a length of the shortest path from s to i and Q[i] is a number of shortest paths between s and i.
How can we recalculate these arrays?
First of all, lets set D[s] = 0 and Q[s] = 1. Then we can use well-known bfs:
while queue with vertexes is not empty
get v from queue
set v as visited
for all u, there's an edge from v to u
if u is not visited yet
D[u] = D[v] + 1
Q[u] = Q[v]
push u into the queue
else if D[v] + 1 == D[u]
Q[u] += Q[v]
The answer is Q[e].
Modify your breadth first search to keep going until it starts finding longer paths, rather than stopping and returning just the first one.
Assume I have a directed, weighted graph with positive or negative weights, (with no zero or negative weighted loops).
The graph is Bellman-Ford analized, meaning each vertex holds the data of the lightest path to it from the source vertex, and its predecessor in the lightest path.
What is the most efficient way to store the number of different shortest paths from the source to each vertex?
I am willing to make it in linear time - O(V+E) if possible.
You can do it pretty efficiently if you have no negative edges as well.
Let the shortest path to node v be denoted as D(v)
sort vertices by distances - O(VlogV)
Denote P(v) - number of paths leading from the source to v.
Now, you can use DP to solve this relation (from first to last):
P(source) = 1
P(v) = sum { P(u) | (u,v) is an edge and D(u) + w(u,v) = D(v) }
Complexity of the algorithm is O(VlogV + E)
Correctness proof: by induction (guidelines):
Base clause for source, there is a single path (the empty path).
let us assume P(v) is correct for every v such that D(v) < D(u).
For every shortest path that ends with u, it must go through one of the vertices such that D(v) < D(u). Given a shortest path source->...->v->u, the path is counted in P(v). In addition, it is not counted for any other P(v'), so it is counted exactly once in sum { P(u) | (u,v) is an edge and D(u) + w(u,v) = D(v) }.
In addition, for any path which is not shortest path, from induction hypothesis, it is not counted for any v such that D(v)<D(u), so the path must be generated in the last step, but the restriction (u,v) is an edge and D(u) + w(u,v) = D(v) is preventing it, so we do not count any non-shortest path.
QED
We are given a directed graph G (possibly with cycles) with positive edge weights, and the minimum distance D[v] to every vertex v from a source s is also given (D is an array this way).
The problem is to find the array N[v] = number of paths of length D[v] from s to v,
in linear time.
Now this is a homework problem that I've been struggling with for quite long. I was working along the following thought : I'm trying to remove the cycles by suitably choosing an acyclic subgraph of G, and then try to find shortest paths from s to v in the subgraph.
But I cannot figure out explicitly what to do, so I'd appreciate any help, as in a qualitative idea on what to do.
You can use dynamic programming approach in here, and fill up the number of paths as you go, if D[u] + w(u,v) = D[v], something like:
N = [0,...,0]
N[s] = 1 //empty path
For each vertex v, in *ascending* order of `D[v]`:
for each edge (u,v) such that D[u] < D[v]:
if D[u] + w(u,v) = D[v]: //just found new shortest paths, using (u,v)!
N[v] += N[u]
Complexity is O(VlogV + E), assuming the graph is not sparsed, O(E) is dominanting.
Explanation:
If there is a shortest path v0->v1->...->v_(k-1)->v_k from v0 to v_k, then v0->...->v_(k-1) is a shortest path from v0 to v_k-1, thus - when iterating v_k - N[v_(k-1)] was already computed fully (remember, all edges have positive weights, and D[V_k-1] < D[v_k], and we are iterating by increasing value of D[v]).
Therefor, the path v0->...->v_(k-1) is counted in the number N[V_(k-1)] at this point.
Since v0->...->v_(k-1)-v_k is a shortest path - it means D[v_(k-1)] + w(v_k-1,v_k) = D[v_k] - thus the condition will hold, and we will add the count of this path to N[v_k].
Note that the proof for this algorithm will basically be induction that will follow the guidelines from this explanation more formally.