Finding all shortest paths from source to all vertices in a digraph - algorithm

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.

Related

Intuition behind the algorithm to compute single source shortest path for every vertex in DAG

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.

Finding the number of all the shortest paths between two nodes in directed unweighted graph

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.

Find the minimum weight cycle that contains a specific edge

given a graph:
- oriented,
- strongly connected and
- weighed (the weights are all positive)
I have to write a function that taken as input an edge (u, v), calculate the weight of the cycle of minimum weight that contains this edge.
I thought I'd do as follows but the procedure is inaccurate and incomplete:
- Starts a bfs visit starting from node u
- Keep in a variable the temporary weight
- When you arrive to v choose the minimum of the previous weights.
How do I keep track of previous weights? How to write the pseudocode?
I have no idea how to get started so someone help me?
Thanks
This can be reduced to Shortest Path Problem:
Find the shortest path from v to u, then the shortest cycle that contains (u,v), is v->...->u->v, where v->...->u is the shortest path from v to u as found by the shortest path algorithm.
It can be solved efficiently using Dijkstra's Algorithm, since there are no negative weights in the graph.
Correctness Proof:
Assume there is a cheaper cycle v1->v2->...vi->u->v->v_i+1->...->vn->v1. Let's say it weights x < d(v,u) + w(u,v)
Since it's a cycle, we can look at it as v->v_i+1->....->vn->v1->...->vi->u->v.
The weight of the cycle didn't change, and is still x. This means x=w(v,v_i+1) + ... + w(vn,v1) + ... + w(v_i-1,vi) + w(vi,u) + w(u,v)
But this gives us w(v,v_i+1) + ... + w(vn,v1) + ... + w(v_i-1,vi) + w(vi,u) + w(u,v) - w(u,v) < d(v,u), and we have found a shorter path from v to u, than d(v,u), which is contradicting correctness of Dijkstra's Algorithm.
QED

Number of lightest paths from single source vertex

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

Maximum weighted path between two vertices in a directed acyclic Graph

Love some guidance on this problem:
G is a directed acyclic graph. You want to move from vertex c to vertex z. Some edges reduce your profit and some increase your profit. How do you get from c to z while maximizing your profit. What is the time complexity?
Thanks!
The problem has an optimal substructure. To find the longest path from vertex c to vertex z, we first need to find the longest path from c to all the predecessors of z. Each problem of these is another smaller subproblem (longest path from c to a specific predecessor).
Lets denote the predecessors of z as u1,u2,...,uk and dist[z] to be the longest path from c to z then dist[z]=max(dist[ui]+w(ui,z))..
Here is an illustration with 3 predecessors omitting the edge set weights:
So to find the longest path to z we first need to find the longest path to its predecessors and take the maximum over (their values plus their edges weights to z).
This requires whenever we visit a vertex u, all of u's predecessors must have been analyzed and computed.
So the question is: for any vertex u, how to make sure that once we set dist[u], dist[u] will never be changed later on? Put it in another way: how to make sure that we have considered all paths from c to u before considering any edge originating at u?
Since the graph is acyclic, we can guarantee this condition by finding a topological sort over the graph. topological sort is like a chain of vertices where all edges point left to right. So if we are at vertex vi then we have considered all paths leading to vi and have the final value of dist[vi].
The time complexity: topological sort takes O(V+E). In the worst case where z is a leaf and all other vertices point to it, we will visit all the graph edges which gives O(V+E).
Let f(u) be the maximum profit you can get going from c to u in your DAG. Then you want to compute f(z). This can be easily computed in linear time using dynamic programming/topological sorting.
Initialize f(u) = -infinity for every u other than c, and f(c) = 0. Then, proceed computing the values of f in some topological order of your DAG. Thus, as the order is topological, for every incoming edge of the node being computed, the other endpoints are calculated, so just pick the maximum possible value for this node, i.e. f(u) = max(f(v) + cost(v, u)) for each incoming edge (v, u).
Its better to use Topological Sorting instead of Bellman Ford since its DAG.
Source:- http://www.utdallas.edu/~sizheng/CS4349.d/l-notes.d/L17.pdf
EDIT:-
G is a DAG with negative edges.
Some edges reduce your profit and some increase your profit
Edges - increase profit - positive value
Edges - decrease profit -
negative value
After TS, for each vertex U in TS order - relax each outgoing edge.
dist[] = {-INF, -INF, ….}
dist[c] = 0 // source
for every vertex u in topological order
if (u == z) break; // dest vertex
for every adjacent vertex v of u
if (dist[v] < (dist[u] + weight(u, v))) // < for longest path = max profit
dist[v] = dist[u] + weight(u, v)
ans = dist[z];

Resources