Dynamic Programming - Edges difference problem - algorithm

I just started learning about Dynamic Programming, and in my assignment I was required to describe an algorithm that solves the following problem:
Let G be a directed graph, where every edge is colored either green or yellow, and a source vertex s. For every vertex in V, find a path that the difference between the number of green and yellow edges is minimal. That algorithm needs to be O(|V|+|E|) complexity for each vertex.
Input: Given a directed graph G=(V, E), a source vertex s in V and edges colored with this coloring function: For every edge e in the graph, c(e)->{yellow, green}. There is a path to every vertex v in V from the source vertex s.
The weight of a path 'P' in the graph, is the difference between the number of green edges and the number of yellow edges in the graph
Output: For every vertex v in V, return the minimal weight of a path P from s to v.
So I started thinking about a solution to this problem. I realized that I can exchange the colors with numbers, -1 and 1 and work from there, but so far I haven't been able to find a solution.
My most fleshed out solution looks at the group of neighbors of target a vertex and does the following:
Find the minimum weight between:
The sum of the "weight" of the edge (-1, 1) leading to a vertex 'k' from the current vertex's neighbor group, and the optimum of 'k'.
The optimum of the other neighbors, excluding the vertex 'k'.
terminate when reaching s or the neighbors group is empty.
However, this solution doesn't feel right, as it doesn't look at a vertex - but at a group of vertices, and I don't think it meets the complexity demands. I tried writing the formula: image
I tried experimenting with solutions that start from the vertex s and end at a target vertex v, but I was unable to reach a solid termination condition. For example, it can't terminate when reaching v, since there might be cycles involving v that result in a minimum result.
I was hoping to get some guidance on this problem, thanks in advance!

This doesn't necessarily strike me as a case for dynamic programming, so maybe I've missed something and there's a quicker dynamic solution, but you can achieve an O(VE) running time using a modified Bellman-Ford. This asymptotic time bound is not the same as O(V + E) per vertex! But for a connected graph (since the source can reach all the vertices) it is the same overall.
I'll leave you to look up the details of the Bellman Ford algorithm (for single source shortest paths), in the spirit of it being an assignment, but suffice it to say that your vertices could store a positive score for more yellow than green, a negative score for the opposite, and their weight in either case would be the absolute value of this attribute. Your 'relax' function would then operate as follows, assuming we use a score attribute on each vertex (this score is not the weight, it can be positive or negative):
RELAX(u, v):
new_score = u.score
if the edge u -> v is green:
new_score -= 1
else:
new_score += 1
if abs(new_score) < v.score:
v.score = new_score

Related

Backtrack after running Johnson algorithm

I have a question which I was asked in some past exams at my school and I can't find an answer to it.
Is it possible knowing the final matrix after running the Johnson Algorithm on a graph, to know if it previously had negative cycles or not? Why?
Johnson Algorithm
Johnson's Algorithm is a technique that is able to compute shortest paths on graphs. Which is able to handle negative weights on edges, as long as there does not exist a cycle with negative weight.
The algorithm consists of (from Wikipedia):
First, a new node q is added to the graph, connected by zero-weight edges to each of the other nodes.
Second, the Bellman–Ford algorithm is used, starting from the new vertex q, to find for each vertex v the minimum weight h(v) of a path from q to v. If this step detects a negative cycle, the algorithm is terminated.
Next the edges of the original graph are reweighted using the values computed by the Bellman–Ford algorithm: an edge from u to v, having length w(u, v), is given the new length w(u,v) + h(u) − h(v).
Finally, q is removed, and Dijkstra's algorithm is used to find the shortest paths from each node s to every other vertex in the reweighted graph.
If I understood your question correctly, which should have been as follows:
Is it possible knowing the final pair-wise distances matrix after running the Johnson Algorithm on a graph, to know if it originally had any negative-weight edges or not? Why?
As others commented here, we must first assume the graph has no negative weight cycles, since otherwise the Johnson algorithm halts and returns False (due to the internal Bellman-Form detection of negative weight cycles).
The answer then is that if any negative weight edge e = (u, v) exists in the graph, then the shortest weighted distance between u --> v cannot be > 0 (since at the worst case you can travel the negative edge e between those vertices).
Therefore, at least one of the edges had negative weight in the original graph iff any value in the final pair-wise distances is < 0
If the question is supposed to be interpreted as:
Is it possible, knowing the updated non-negative edge weights after running the Johnson Algorithm on a graph, to know if it originally had any negative-weight edges or not? Why?
Then no, you can't tell.
Running the Johnson algorithm on a graph that has only non-negative edge weights will leave the weights unchanged. This is because all of the shortest distances q -> v will be 0. Therefore, given the edge weights after running Johnson, the initial weights could have been exactly the same.

Efficient algorithm to extract a subgraph within a maximum distance from multiple vertices

I have an algorithmic problem where there's a straightforward solution, but it seems wasteful. I'm wondering if there's a more efficient way to do the same thing.
Here's the problem:
Input: A large graph G with non-negative edge weights (interpreted as lengths), a list of vertices v, and a list of distances d the same length as v.
Output: The subgraph S of G consisting of all of the vertices that are at a distance of at most d[i] from v[i] for some i.
The obvious solution is to use Dijkstra's algorithm starting from each v[i], modified so that it bails out after hitting a distance of d[i], and then taking the union of the subgraphs that each search traverses. However, in my use case it's frequently going to be the case that the search trees from the v[i]s overlap substantially. That means the Dijkstra approach will wastefully traverse the vertices in the overlap multiple times before I take the union.
In the case that there is only one vertex in v, the Dijkstra approach runs in O(|S|log|S|), taking |S| to be the number of vertices (my graph is sparse, so I ignore the edges term). Is it possible to achieve the same asymptotic run time when v has more than one vertex?
My first idea was to combine the searches out of each v[i] into the same priority queue, but the "bail out" condition mentioned above complicates this approach. Sometimes a vertex will be reached in a shorter distance from one v[i], but you would still want to search through it from another v[j] if the second vertex has a larger d[j] allotted to it.
Thanks!
You can solve this with the complexity of a single Dijkstra run.
Let D be the maximum of the distances in d.
Define a new start vertex, and give it edges to each of the vertices in v.
The length of the edge between start and v[i] should be set to D-d[i].
Then in this new graph, S is given by all vertices within a length D of the start vertex, so apply Dijkstra to the start vertex.

Minimum sum of distances from sensor nodes to all others

Is there a way to compute (accurate or hevristics) this problem on medium sized (up to 1000 nodes) weighted graph?
Place n (for example 5) sensors in nodes of the graph in such way that the sum of distances from every other node to the closest sensor will be minimal.
I'll show that this problem is NP-hard by reduction from Vertex Cover. This applies even if the graph is unweighted (you don't say whether it's weighted or not).
Given an unweighted graph G = (V, E) and an integer k, the question asked by Vertex Cover is "Does there exist a set of at most k vertices such that every edge has at least one endpoint in this set?" We will build a new graph G' = (V', E), which is the same as G except that all isolated vertices have been discarded, solve your problem on G', and then use it to answer the original question about Vertex Cover.
Suppose there does exist such a set S of k vertices. If we consider this set S to be the locations to put sensors in your problem, then every vertex in S has a distance of 0, and every other vertex is at a distance of exactly 1 away from a vertex that is in S (because if there was some vertex u for which this wasn't true, it would mean that none of u's neighbours are in S, so for each such neighbour u, the edge uv is not covered by the vertex cover, which would be a contradiction.)
This type of problem is called graph clustering. One of the popular methods to solve it is the Markov Cluster (MCL) Algorithm. A web search should provide some implementation examples. However it does not generally provide the optimal solution.

Shortest paths with 2 constraints (Weight and Colour)

Input: We have a directed graph G=(V,E) and each edge has a weight and a colour {red,green}. We are also given a starting node s.Problem/Algorithm: Can we find for all u edges of G, the shortest paths s-u with at most k red edges ? First approach: We save for each node the shortest path with 0,1...k red edges. We modify Dijkstra's algorithm and depending on the colour of the edges we are looking into, we update the distances respectively. This approach fails due to its complexity. Second approach: We make k copies of G graph (G1,G2 ...Gk+1). In order to utilise the k red edges constraint, while we are searching for shortest paths with Dijkstra, every time we "meet" a red edge {ui,vi} in Gi, we connect ui with vi+1 in Gi+1. Because Gk+1 doesn't have any red edges, we can only reach Gk+1 with at most k edges.But it fails. For example with k=2 if a 2 red edges shortest path is found to X node then will not take into consideration a heavier path with less red edges which could lead to an undiscovered node. (If i had enough reputation i could post an image as example). Any ideas ?
I think your approaches are actually equivalent, provided that for approach #1, you record only the shortest distance to each node for each number of red edges used -- you don't need to record the entire path (just as you don't need to record it for ordinary Dijkstra on an ordinary shortest path problem)
Also this approach is sound. In particular, your reasoning that approach #2 is faulty is itself wrong: for any node X in the original graph, there is no single corresponding node X in the new graph; instead there are separate vertices for each number of red edges used. So the two paths "to X" you are considering are not actually to the same node: one is to (X, 2 red edges used) and one is to e.g. (X, 1 red edge used). Then you can use a single Dijkstra run to calculate shortest paths to all k+1 copies of every vertex (i.e. to the vertices (v, i red edges used) for each 0 <= i <= k and for each v in V(G)), and return the lowest. (I'm assuming here that when you wrote "Can we find for all u edges of G, the shortest paths s-u", you meant "for all nodes u of G, the shortest paths s-u".)
Finally, you need to make sure that for any red edge {u, v} in G, you delete the corresponding edge {ui, vi} for all Gi (as well as add in the edge {ui, vi+1}). You probably intended this, but you weren't explicit about it.

Dijkstra's shortest path algorithm won't work

I have a graph with positive edge weights and positive node weights. The length of a path is defined as the sum of all the edge weights along the path, plus the maximum node weight encountered along the path.
I'd initially thought that a modified Dijkstra would work, but I found a test case where it would fail. How should I go about solving this problem? Are there any standard algorithms I should look at?
My modified Dijkstra is as follows: At each node I record the shortest path so far, and also the maximum node weight I've seen so far, and use that to calculate the length to neighboring nodes. Please see my comment for the details.
Here's a graph where Dijkstra fails:
http://i.imgur.com/FQhRzXV.jpg
The numbers in green are the node labels. Everything in blue is weights (node and edge weights). Lets say I want to compute the shortest path between nodes 1 and 7 (labeled in green). The problem with Dijkstra is that the node 4 always records the path 1-8-9-4 since its shorter than path 1-2-3-4 (former length 9 vs latter length 13). But to reach node 7, path 1-8-9-4-5-6-7 is longer than 1-2-3-4-5-6-7.
If you can forgive one order larger polynomial time, then fairly easy algorithm:
ModifiedShortestPath(u, v, G) {
X = StandardardShorestPath(u, v, G);
E = heaviest edge in X
F = all edges in G of weight >= E
Y = ModifiedShortestPath(u, v, G - F); // recur here on G without the F edges
return Min(X, Y);
}
The runtime of this is |E| times more than your standard shortest path.
Your graph is not that clear to begin with (too many values in blue of unclear role), which makes answers even more difficult. A much better question, a simpler graph and some straight answers in this post.
What made it clear for me, and allowed me to correct my implementation and get the correct results, was that at the end of each repetition in the loop, when it was time to pick the next node/vertex, whose unvisited neighbours I should examine, I had to pick from the whole pool of unvisited vertices, not just from the unvisited neighbours of the currently examined node. I was under the false impression that once you pick a path at a crossroad, because the greedy nature of the algorithm takes you there, you can only follow it to the end, unvisited after unvisited node. No. You pick the next globally unvisited node each time based on the smallest tentative value, regardless of its position in the graph or whether it is connected to the current node.
I Hope that clears the confussion that others like me have experienced and has led them here.

Resources