I want to find the cheapest path between 2 vertices and I can choose one path which I can go for free., e.g:
Cheapest path between vertices 1 and 6 is 1-3-4-5-6 - I go on edge 1-3 (cost 30) for free and it gives me total cost 21.
Is there any other way than checking all paths one by one?
One way to do it would be to do the following:
Duplicate your graph, so that you have your original graph G with nodes 1,2,etc. and a copy G' with nodes 1',2',etc. and corresponding edges.
For each edge (a,b) of G, make an arc (directed!) from a to b' and another from b to a', both with cost 0.
Finally, use any shortest path algorithm from any vertex of subgraph G to any vertex of G' (1 to 6' in your example).
Basically what happens is that you switch from subgraph G to G' when you use your joker.
You can generalise from there to any number of joker edges by adding extra copies and linking each new one to the last. In that case however you may have to add targets using less jokers in order to account for the cases where the shortest path requires less edges than you have jokers.
Related
Let be a directed graph, and let be an edge-coloring in red and blue. Let s,t be vertices in G. Find a path from s to t (if exists) so that the number of color changes along this path is minimal.
I have tried to do as follows:
Let be the graph obtained by removing all the
blue-colored edges of G. Let be the graph obtained
by removing all the red-colored of G.
Let
be the strongly connected graph of , computed
using this algorithm.
Let be the
strongly connected graph of , computed using
this algorithm.
Color the vertices of
in red, and color the vertices of
in blue.
Let be
the graph obtained by merging with
.
Define the weight of each (existing)
edge in G' as 0.
For each such that u
belongs to the strongly connected component and v
belongs to the strongly connected component do as
follows:
if and add edge to G' and
define its weight as 1.
Use Dijkstra algorithm to find a shortest
path from the blue strongly connected component of s, to both the
blue and red strongly connected components of t.
Use Dijkstra
algorithm to find a shortest path from the red strongly connected
component of s, to both the blue and red strongly connected
components of t.
Let p denote the shortest path among the four we
have just found. (namely, p has minimal number of color alternates). p is a series of strongly connected components.
Expand each of them using DFS, to find a corresponding path in G.
This algorithm can run in O(E+V*log(v)). Can it be improved or simplified?
I don't fully understand your algorithm, specifically in stage 4 you will color every vertex with two different colored edges in two colors - blue and red...
Therefor I will not try and improve your algorithm but will present one of my own - a variant of BFS with time of O(E + V).
The idea: Iterate over the edges of the graph and measure depth as the number of times you switched colors.
Note: We will run the algorithm twice, first assume that the first edge of the path is red, second assume that the first edge of the path is blue, than take the minimum.
Run BFS only on red edges starting from s (which is the first element in the BFS queue), if you viewed a vertex on a blue edge keep it in a different queue.
Mark all of the nodes you saw with the number i (at the beginning i=0).
Take the queue for the blue edges and make it your primary queue.
Run stages 1 to 3 but switch the colors and add 1 to i.
At the end the number in t is the minimal number of swaps performed to reach t.
My graph is as follows:
I need to find a maximum weight subgraph.
The problem is as follows:
There are n Vectex clusters, and in every Vextex cluster, there are some vertexes. For two vertexes in different Vertex cluster, there is a weighted edge, and in the same Vextex cluster, there is no edge among vertexes. Now I
want to find a maximum weight subgraph by finding only one vertex in each
Vertex cluster. And the total weight is computed by adding all weights of the edges between the selected vertex. I add a picture to explain the problem. Now I know how to model this problem by ILP method. However, I do not know how to solve it by an approximation algorithm and how to get its approximation ratio.
Could you give some solutions and suggestions?
Thank you very much. If any unclear points in this description,
please feel free to ask.
I do not think you can find an alpha-approx for this problem, for any alpha. That is because if such an approximation exists, then it would also prove that the unique games conjecture(UGC) is false. And disproving (or proving) the UGC is a rather big feat :-)
(and I'm actually among the UGC believers, so I'd say it's impossible :p)
The reduction is quite straightforward, since any UGC instance can be described as your problem, with weights of 0 or 1 on edges.
What I can see as polynomial approximation is a 1/k-approx (k the number of clusters), using a maximum weight perfect matching (PM) algorithm (we suppose the number of clusters is even, if it's odd just add a 'useless' one with 1 vertex, 0 weights everywhere).
First, you need to build a new graph. One vertex per cluster. The weight of the edge u, v has the weight max w(e) for e edge from cluster u to cluster v. Run a max weight PM on this graph.
You then can select one vertex per cluster, the one that corresponds to the edge selected in the PM.
The total weight of the solution extracted from the PM is at least as big as the weight of the PM (since it contains the edges of the PM + other edges).
And then you can conclude that this is a 1/k approx, because if there exists a solution to the problem that is more than k times bigger than the PM weight, then the PM was not maximal.
The explanation is quite short (lapidaire I'd say), tell me if there is one part you don't catch/disagree with.
Edit: Equivalence with UGC: unique label cover explained.
Think of a UGC instance. Then, every node in the UGC instance will be represented by a cluster, with as many nodes in the cluster as there are colors in the UGC instance. Then, create edge with weight 0 if they do not correspond to an edge in the UGC, or if it correspond to a 'bad color match'. If they correspond to a good color match, then give it the weight 1.
Then, if you find the optimal solution to an instance of your problem, it means it corresponds to an optimal solution to the corresponding UGC instance.
So, if UGC holds, it means it is NP-hard to approximate your problem.
Introduce a new graph G'=(V',E') as follows and then solve (or approximate) the maximum stable set problem on G'.
Corresponding to each edge a-b in E(G), introduce a vertex v_ab in V'(G') where its weight is equal to the weight of the edge a-b.
Connect all of vertices of V'(G') to each other except for the following ones.
The vertex v_ab is not connected to the vertex v_ac, where vertices b and c are in different clusters in G. In this manner, we can select both of these vertices in an stable set of G' (Hence, we can select both of the corresponding edges in G)
The vertex v_ab is not connected to the vertex v_cd, where vertices a, b, c and d are in different clusters in G. In this manner, we can select both of these vertices in an stable set of G' (Hence, we can select both of the corresponding edges in G)
Finally, I think you can find an alpha-approximation for this problem. In other words, in my opinion the Unique Games Conjecture is wrong due to the 1.999999-approximation algorithm which I proposed for the vertex cover problem.
I'm trying to solve this work problem, but I'm having some difficuly, since I suck at recursion.
My question is: is there a way where I can pick a node in a graph and traverse the graph all the way through back to the same node where I started, but the nodes can only be visited once? And of course to save the resulting edges traversed.
The graph is unweighted, but it is coordinates in a 2D x and y coordinate system, so each coordinate has an x and y value, meaning the edges can weighted by calculating the distance between the coordinates. If that helps...
I'm not completely sure I understand, but here is a suggestion: pick a node n0, then an edge e=(n0,n1). Then remove that edge from the graph, and use a breadth-first search to find the shortest path from n1 back to n0 if it exists.
Another suggestion, which might help you to control the length of the resulting path better: Pick a starting node n0 and find a spanning tree T emanating from n0. Remove n0, and T will (hopefully) break into components. Find an edge e=(n1,n2) from one component to another. Then that edge, plus the edges in T connecting the n1 to n0, plus the edges in T connecting n2 to n0, is a cycle with the properties you desire.
Heyo!
So I've got this directed and/or undirected graph with a bunch of vertices and edges. In this graph there is a start vertex and an end vertex. There's also a subset of vertices which are coloured red (this subset can include the start and end vertices). Also, no pair of vertices can have more than one edge between them.
What I have to do is to find:
A) The shortest path that passes no red vertices
B) If there is a path that passes at least one red vertex
C) The path with the greatest amount of red vertices
D) The path with the fewest amount of red vertices
For A I use a breadth first search ignoring red branches. For B I simply brute force it with a depth first search of the graph. And for C and D I use dynamic programming, memoizing the number of red vertices I find in all paths, using the same DFS as in B.
I am moderately happy with all the solutions and I would very much appreciate any suggestions! Thanks!!
For A I use a breadth first search ignoring red branches
A) is a Typical pathfinding problem happening in the sub-graph that contains no red edges. So your solution is good (could be improved with heuristics if you can come up with one, then use A*)
For B I simply brute force it with a depth first search of the graph
Well here's the thing. Every optimal path A->C can be split at an arbitrary intermediate point B. A Nice property of optimal paths, is that every sub-path is optimal. So A->B and B->C are optimal.
This means if you know you must travel from some start to some end through an intermediary red vertex, you can do the following:
Perform a BFS from the start vertex
Perform a BFS from the endvertex backwards (If your edges are directed - as I think - you'll have to take them in reverse, here)
Alternate expanding both BFS so that both their 'edge' (or open lists, as they are called) have the same distance to their respective start.
Stop when:
One BFS hits a red vertex encountered by (or in the 'closed' list of) the other one. In this case, Each BFS can construct the optimal path to that commen vertex. Stitch both semi-paths, and you have your optimal path with at least a red vertex.
One BFS is stuck ('open' list is empty). In this case, there is no solution.
C) The path with the greatest amount of red vertices
This is a combinatorial problem. the first thing I would do is make a matrix of reachability of [start node + red nodes + end nodes] where:
reachability[i, j] = 1 iff there is a path from node i to node j
To compute this matrix, simply perform one BFS search starting at the start node and at every red node. If the BFS reaches a red node, put a 1 in the corresponding line/column.
This will abstract away the underlying complexity of the graph, and make an order of magnitude speedup on the combinatorial search.
The problem is now a longest path problem through that connectivity matrix. dynamic programming would be the way to go indeed.
D) The path with the fewest amount of red vertices
Simply perform a Dijkstra search, but use the following metric when sorting the nodes in the 'open' list:
dist(start, a) < dist(start, b) if:
numRedNodesInPath(start -> a) < numRedNodesInPath(start -> b)
OR (
numRedNodesInPath(start -> a) == numRedNodesInPath(start -> b)
AND
numNodesInPath(start -> a) < numNodesInPath(start -> a)
)
For this, when discovering new vertices, you'll have to store the path leading up to them (well, just the nb of nodes in the path, as well as the nb of red nodes, separately) in a dedicated map to be fetched. I mention this because usually, the length of the path is stored implicitly as the position of the verrtex in the array. You'll have to enforce it explicitely in your case.
Note on length optimality:
Even though you stated you did not care about length optimality outside of problem A), the algorithm I provided will produce shortest-length solutions. In many cases (like in D) it helps Dijkstra converge better I believe.
Let's say we have a fully connected directed graph G. The vertices are [a,b,c]. There are edges in both directions between each vertex.
Given a starting vertex a, I would like to traverse the graph in all directions and save the path only when I hit a vertex which is already in the path.
So, the function full_paths(a,G) should return:
- [{a,b}, {b,c}, {c,d}]
- [{a,b}, {b,d}, {d,c}]
- [{a,c}, {c,b}, {b,d}]
- [{a,c}, {c,d}, {d,b}]
- [{a,d}, {d,c}, {c,b}]
- [{a,d}, {d,b}, {b,c}]
I do not need 'incomplete' results like [{a,b}] or [{a,b}, {b,c}], because it is contained in the first result already.
Is there any other way to do it except of generating a powerset of G and filtering out results of certain size?
How can I calculate this?
Edit: As Ethan pointed out, this could be solved with depth-first search method, but unfortunately I do not understand how to modify it, making it store a path before it backtracks (I use Ruby Gratr to implement my algorithm)
Have you looked into depth first search or some variation? A depth first search traverses as far as possible and then backtracks. You can record the path each time you need to backtrack.
If you know your graph G is fully connected there is N! paths of length N when N is number of vertices in graph G. You can easily compute it in this way. You have N possibilities of choice starting point, then for each starting point you can choose N-1 vertices as second vertex on a path and so on when you can chose only last not visited vertex on each path. So you have N*(N-1)*...*2*1 = N! possible paths. When you can't chose starting point i.e. it is given it is same as finding paths in graph G' with N-1 vertices. All possible paths are permutation of set of all vertices i.e. in your case all vertices except starting point. When you have permutation you can generate path by:
perm_to_path([A|[B|_]=T]) -> [{A,B}|perm_to_path(T)];
perm_to_path(_) -> [].
simplest way how to generate permutations is
permutations([]) -> [];
permutations(L) ->
[[H|T] || H <- L, T <- permutations(L--[H])].
So in your case:
paths(A, GV) -> [perm_to_path([A|P]) || P <- permutations(GV--[A])].
where GV is list of vertices of graph G.
If you would like more efficient version it would need little bit more trickery.