i'm looking for an algorithm that finds the shortest path between two vertices (i and j) in a graph that contains a specified number of edges, n. i have a dynamic program that looks at the shortest path to the destination with n-1 edges, but how can i be sure that the shortest path being found starts at i?
I guess the edges have different costs / lengths and that the constraint is that there are n edges, and among all paths from i to j that have exactly n individual edges, the goal is to find the one that has least total cost / length.
If you do this using dynamic programming, the recurrences are
spath(f, t, n): --- returns shortest path from 'f' to 't' that has 'n' edges
spath(x, x, 0) = [x] --- path that has only one vertex
spath(x, y, 0) = NO PATH --- when x != y
spath(f, t, n) =
min cost path over (x is any node that is connected to t):
spath(f, x, n-1) + [t] (x can be appended because there is edge x - t)
Your wording is ambiguous. Is n the number of edges in the graph or the number of hops in the path? If the latter, then it's not a shortest path anymore. If you mean the former then any popular shortest-path algorithm such as Dijkstra's will work. If you mean the latter, then do n iterations of BFS starting at i and locate your j in the nth frontier. If it's not there, then there's no path from i to j in n hops. Walk down the BFS frontiers to read your path.
Related
Given a weighted graph G=(V,E) which doesnt include negative cycles, a natural number k, and two verticles: s,t.
How can I find the cheapest route from s to t which its length can be divied by k?
Prepare a new graph G' with vertices V × {0, 1, …, n−1} and for each arc v → w of length ℓ in G, arcs (v, x) → (w, (x + ℓ) mod k). Then use Dijkstra's algorithm to find a shortest path from (s, 0) to (t, 0).
Use BFS with a priority queue, so as to always examine states (= paths from s) that are shortest. Unlike normal Dijkstra, your states are full paths, and you can revisit already-visited vertices as often as they are encountered.
I cannot prove that such an algorithm would be optimal, but at least it should be correct, always returning a valid shortest-path answer if it exists. Runtime for certain graphs and values of K would be very high, and the algorithm may not finish at all if there are no k-divisible paths from s to t but there are loops with a path-length divisible by k. You could find and filter those out first by using a preliminary DFS.
Imagine you are given a weighted undirected complete graph with n nodes with non-negative weights Cij, where for i = j Cii = 0, and for i != j Cij > 0. Suppose you have to find the maximal shortest path between any two nodes i and j. Here, you can easily use Floyd-Warshall, or use Dijkstra n times, or whatever, and then just to find the maximum among all n^2 shortest paths.
Now assume that Cij are not constant, but rather can take two values, Aij and Bij, where 0 <= Aij <= Bij. We also have Aii = Bii = 0. Assume you also need to find the maximal shortest path, but with the constraint that m edges must take value Bij, and other Aij. And, if m > n^2, then all edges are equal to Bij. But, when finding shortest path i -> p1 -> ... -> pk -> j, you are intesrested in the worst case, in the sense that on that path you need to choose those edges to take value of Bij, such that path value is maximal if you have fixed nodes on its direction.
For example, a if you have path of length four i-k-l-j, and, in optimal solution on that path only one weight is changed to Bij, and other take value of Aij. And let m1 = Bik + Akl + Alj, m2 = Aik + Bkl + Alj, m3 = Aik + Akl + Blj, the value of that path is max{m1, m2, m3}. So, among all paths between i and j, you have to choose one such that maximal value (described as in this example) is minimal (which is a variant of definition of shortest path). And you have to do it for all pairs i and j.
You are not given the constraint how many you need to vary on each path, but rather value of m, a number of weights that should be varied in the complete graph. And the problem is to find the maximum value of the shortest path, as described.
Also, my question is: is this NP-hard problem, or there exists some polynomial solution?
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.
Given a directed graph G=(V,E) and a weight function w : E - > R+ (only positive weights for edges in the graph) , I need to find all the shortest paths from every vertex v in V to a given vertex k.
I've thought about reversing the edges in the graph and then running Dijkstra's algorithm from the vertex k. I wonder whether a shortest path p from k to v1 is actually the shortest path from v1 to k in the original graph ( before reversing edges ).
I'd be grateful if anyone could explain if and why it does / does not happen.
Thanks in advance.
(This won't be the most formal proof in the world, but hopefully its good enough to convince yourself).
Lets say for a vertex v, in graph G, the shortest path from v to k is of length m.
The two things you want to know are:
1. In the reversed graph, G*, there is a path of length m from k to v.
2. In the reversed graph, G*, there are no paths from k to v that are shorter than m.
Before I start, can we take one thing on faith:
Lemma 1: If you have a directed path from vertex v to vertex w, and you reverse every edge on the path, then you have a path from vertex w to vertex v. This is provable, but I think its fairly common sense. I'll prove it if you want me to.
For point 1: Consider the path in G from v to k consisting of m edges. If you reverse each of these edges, you will have a path from k to v of length m (by Lemma 1).
For point 2: Suppose there exists a path in the reversed graph G*, from k to v of length n < m. If you reverse this path, then there is a path of length n from v to k (Lemma 1). This means that there is a path from v to k in the original graph that is shorter than m, contradicting the statement that the path of length m is the shortest.
Find the shortest path through a graph in efficient time, with the additional constraint that the path must contain exactly n nodes.
We have a directed, weighted graph. It may, or may not contain a loop. We can easily find the shortest path using Dijkstra's algorithm, but Dijkstra's makes no guarantee about the number of edges.
The best we could come up with was to keep a list of the best n paths to a node, but this uses a huge amount of memory over vanilla Dijkstra's.
It is a simple dynamic programming algorithm.
Let us assume that we want to go from vertex x to vertex y.
Make a table D[.,.], where D[v,k] is the cost of the shortest path of length k from the starting vertex x to the vertex v.
Initially D[x,1] = 0. Set D[v,1] = infinity for all v != x.
For k=2 to n:
D[v,k] = min_u D[u,k-1] + wt(u,v), where we assume that wt(u,v) is infinite for missing edges.
P[v,k] = the u that gave us the above minimum.
The length of the shortest path will then be stored in D[y,n].
If we have a graph with fewer edges (sparse graph), we can do this efficiently by only searching over the u that v is connected to. This can be done optimally with an array of adjacency lists.
To recover the shortest path:
Path = empty list
v = y
For k= n downto 1:
Path.append(v)
v = P[v,k]
Path.append(x)
Path.reverse()
The last node is y. The node before that is P[y,n]. We can keep following backwards, and we will eventually arrive at P[v,2] = x for some v.
The alternative that comes to my mind is a depth first search (as opposed to Dijkstra's breadth first search), modified as follows:
stop "depth"-ing if the required vertex count is exceeded
record the shortest found (thus far) path having the correct number of nodes.
Run time may be abysmal, but it should come up with the correct result while using a very reasonable amount of memory.
Interesting problem. Did you discuss using a heuristic graph search (such as A*), adding a penalty for going over or under the node count? This may or may not be admissible, but if it did work, it may be more efficient than keeping a list of all the potential paths.
In fact, you may be able to use backtracking to limit the amount of memory being used for the Dijkstra variation you discussed.
A rough idea of an algorithm:
Let A be the start node, and let S be a set of nodes (plus a path). The invariant is that at the end of step n, S will all nodes that are exactly n steps from A and the paths will be the shortest paths of that length. When n is 0, that set is {A (empty path)}. Given such a set at step n - 1, you get to step n by starting with an empty set S1 and
for each (node X, path P) in S
for each edge E from X to Y in S,
If Y is not in S1, add (Y, P + Y) to S1
If (Y, P1) is in S1, set the path to the shorter of P1 and P + Y
There are only n steps, and each step should take less than max(N, E), which makes the
entire algorithm O(n^3) for a dense graph and O(n^2) for a sparse graph.
This algorith was taken from looking at Dijkstra's, although it is a different algorithm.
let say we want shortest distance from node x to y of k step
simple dp solution would be
A[k][x][y] = min over { A[1][i][k] + A[t-1][k][y] }
k varies from 0 to n-1
A[1][i][j] = r[i][j]; p[1][i][j]=j;
for(t=2; t<=n; t++)
for(i=0; i<n; i++) for(j=0; j<n; j++)
{
A[t][i][j]=BG; p[t][i][j]=-1;
for(k=0; k<n; k++) if(A[1][i][k]<BG && A[t-1][k][j]<BG)
if(A[1][i][k]+A[t-1][k][j] < A[t][i][j])
{
A[t][i][j] = A[1][i][k]+A[t-1][k][j];
p[t][i][j] = k;
}
}
trace back the path
void output(int a, int b, int t)
{
while(t)
{
cout<<a<<" ";
a = p[t][a][b];
t--;
}
cout<<b<<endl;
}