You are given a graph G with N vertices and M edges with N<=10^4 and M<=10^5. Now, you have to add exactly one edge (u,v) to the graph so that the total number of bridges is minimized. G may have multiple edges, but no self loops. On the other hand, the newly generated graph, after adding the edge, G', may have both self loops and multiple edges. If many such (u,v) with u<=v is possible then output the lexicographically smallest one (the vertices are numbered from 1..n).
A trivial idea would be to try all edges in order and then use the bridges finding algorithm to find the number of bridges. This takes time O(V^2 * E), so it is clearly useless. How to do better in terms of runtime ?
EDIT: Following advice by j_random_hacker, I add the following details about the source of the above problem. This is a problem named Computer Network (specifically problem 3) from India's IOI Training Camp '14 Practice Test (Test 3). It was an onsite offline test, so I cannot prove that it is not from a present contest, by giving a link. But I have a PDF of the problem statement.
This is not a complete answer but some ideas to steer you towards it:
To avoid having to run the bridge-finding algorithm after trying each possible edge, it pays to ask: By how much can adding a single edge (u, v) change the number of bridges in a graph G?
If u and v are not already connected by any path in G, then certainly (u, v) will itself become a bridge. What about the "bridgeness" (bridgity? bridgulence?) of all other pairs of vertices? Does it change? (Most importantly: Can any edge go from being a bridge to being a non-bridge? If you can prove that this can never happen, then you can immediately discard all such vertex pairs (u, v) from consideration as they can only ever make the situation worse.)
If u and v are already connected in G, there are 2 possibilities:
Every path P that connects them shares some edge (x, y) (note that x and y are not necessarily distinct from u and v). Then (x, y) is a bridge in G, and adding (u, v) will cause (x, y) to stop being a bridge, because it will then become possible to get from x to y "the long way", by going from x back to u, via the new edge (u, v) to v, and then back up to y. (This assumes that x is closer to u on P than y is, but clearly the argument still works if y is closer: just swap u and v.) There could be multiple such bridges (x, y): in that case, all of them will become non-bridges after (u, v) is added.
There are at least 2 edge-disjoint paths P and Q already connecting u and v. Obviously no edge (x, y) on P or Q can be a bridge, since if (x, y) on P were deleted, it's still possible to get from x to y "the long way" via Q. The question is, again: What about the bridgeness of all other vertex pairs? You should be able to prove that this property doesn't change, meaning that adding the edge (u, v) leaves the total number of bridges unchanged, and can therefore be disregarded as a useless move (unless there are no bridges at all to start with).
We see that 2.1 above is the only case in which adding an edge (u, v) can be useful. Furthermore, it seems that the more bridges we can find in a single path in G, the more of them we can neutralise by choosing to connect the endpoints of that path.
So it seems like "Find the path in G that contains the most bridges" might be the right criterion. But first we need to ask ourselves: Does the number of bridges in a path P accurately count the number of bridges eliminated by adding an edge from the start of P to the end? (We know that adding such an edge must eliminate at least those bridges, but perhaps some others are also eliminated as a "side effect" -- and if so, then we need to count them somehow to make sure that we add the edge that eliminates the most bridges overall.)
Happily the answer is that no other bridges are eliminated. This time I'll do the proof myself.
Suppose that there is a path P from u to v, and suppose to the contrary that adding the edge (u, v) would eliminate a bridge (x, y) that is not on P. Then it must be that the single edge (x, y) is the only path from x to y, and that adding (u, v) would create a second path Q from x, via the edge (u, v) in either direction, to y that avoids the edge (x, y). But for any such Q, we could replace the edge (u, v) in Q with the path P, which from our initial assumption avoids (x, y), and still get a path Q' from x to y that avoids the edge (x, y) -- this means that (x, y) must have already been connected by two edge-disjoint paths (namely the single edge (x, y) and Q'), so it could not have been a bridge in the first place. Since this is a contradiction, it follows that no such "removed as a side effect" bridge (x, y) can exist.
So "Find the path in G that contains the most bridges, and add an edge between its endpoints" definitely gives the right answer -- but there is still a problem: this sounds a lot like the Longest Path problem, which is NP-hard for general graphs, and therefore slow to solve.
However, there is a way out. (There must be: you already have an O(V^2*E) algorithm, so it can't be that your problem is NP-hard :-) ) Think of the biconnected components in your input graph G as being vertices in another graph G'. What do the edges between these vertices (in G') correspond to in G? Do they have any particular structure? Final (big) hint: What is a critical path?
This answer is a spoiler. You should probably think along with j_random_hacker's answer instead.
If I understand your problem correctly:
Think of the graph as a tree of biconnected components. Find the longest path in this tree and link up its ends with the new edge.
There is a linear-time algorithm for finding biconnected components using depth first search. Finding the longest path in a tree takes linear time and can be done using depth-first search---make it do "find the farthest vertex and return both it and its distance" and use that. So this takes linear time overall.
(You can roll it all into a single depth-first search that returns the number of bridge edges in the bridgiest path and the farthest vertex in said bridgiest path.)
Related
The below picture is the representation from the question which was asked to me during samsung interview. I had to write the program to find the minimum distance between I and M. There was an additional constraint that we can change one of the edges. For example, The edge FM can be moved to join edge L and M and the edge value will still be 4.
If you notice, the distance between I and M via I-> E -> F -> G -> M is 20. However, if we change one of the edges such that L to M edge value is 4 now. We have to move edge FM to join L and M now. By this method, the distance between I and M is 20.
An arbitrary edge u, v can be changed to u, t or t,v. It can not be changed to x,y. So one of the vertices in the edge has to be same.
Please find the picture below to illustrate the scenario -
So my problem is that I had to write the program for this. To find the minimum distance between two vertices, I thought of using Djikstra's algorithm. However , I as not sure how to take care of the additional constraint where I had the option of changing one of the vertices. If I could get some help to solve this, I would really appreciate it.
If we move an edge (A, B), the new end should be either the start S or the target T vertex (otherwise, the answer is not optimal).
Let's assume that we move the edge (A, B) and the new end is T (the case when it's S is handled similarly). We need to know the shortest path from S to A that doesn't use this edge (once we know it, we can update the answer with the S->A->T path).
Let's compute the shortest path from S to all other vertices using Dijkstra's algorithm.
Let's fix a vertex A and compute the two minimums of dist[B] + weight(A, B) for all B adjacent to A. Let's iterate over all edges adjacent to A. Let the current edge be (A, B). If dist[B] + weight(A, B) is equal to the first minimum, let d be the second minimum. Otherwise, let d be the first minimum. We need to update the answer with d + weight(A, B) (it means that (A, B) becomes (A, T) now).
This solution is linear in the size of the graph (not counting the Dijkstra's algorithm run time).
To avoid code duplication, we can handle the case when the edge is redirected to S by swapping S and T and running the same algorithm (the final answer is the minimum of the results of these two runs).
In the graph you've shown, the shortest path I see is I -> E -> F -> M with a length of 13.
Moving the edge F -> M so that it connects L -> M just makes things worse. The new shortest path is I -> E-> F -> L -> M with a length of 18.
The obvious answer is to move edge F -> M so that it connects I directly to M, giving a length of 4.
In other words, find the shortest edge that's connected to I or M and use it to connect I directly to M.
For future reference, it's highly unlikely that you'll be asked to implement Djikstra's algorithm from memory in an interview. So you need to look for something simpler.
I want to decompose a directed acyclic graph into minimum number of components such that in each component the following property holds true-
For all pair of vertices (u,v) in a components, there is a path from u to v or from v to u.
Is there any algorithm for this?
I know that when the or is replaced by and in the condition, it is same as finding the number of strongly connected components(which is possible using DFS).
*EDIT: * What happens if the Directed graph contains cycles (i.e. it is not acyclic)?
My idea is to order the graph topologically O(n) using DFS, and then think about for what vertices can this property be false. It can be false for those who are joining from 2 different branches, or who are spliting into 2 different branches.
I would go from any starting vertex(lowest in topological ordering) and follow it's path going into random branches, till you cannot go further and delete this path from graph(first component).This would be repeated till the graph is empty and you have all such components.
It seems like a greedy algorithm, but consider you find a very short path in the first run(by having a random bad luck) or you find a longest path(good luck). Then you would still have to find that small branch component in another step of algorithm.
Complexity would be O(n*number of components).
When there is and condition, you should be considering any oriented graph, as DAG cannot have strongly connected component.
The two existing answers both have problems that I've outlined in comments. But there's a more fundamental reason why no decomposition into components can work in general. First, let's concisely express the relation "u and v belong in the same component of the decomposition" as u # v.
It's not transitive
In order to represent a relation # as vertices in a component, that relation must be an equivalence relation, which means among other things that it must transitive: That is, if x # y and y # z, it must necessarily be true that x # z. Is our relation # transitive? Unfortunately the answer is "No", since it may be that there is a path from x to y (so that x # y), and a path from z to y (so that y # z), but no path from x to z or from z to x (so that x # z does not hold), as the following graph shows:
z
|
|
v
x----->y
The problem is that according to the above graph, x and y belong in the same component, and y and z belong in the same component, but x and z belong in different components, which is a contradiction. This means that, in general, it's impossible to represent the relationship # as a decomposition into components.
If an instance happens to be transitive
So there is no solution in general -- but there can still be input graphs for which the relation # happens to be transitive, and for which we can therefore compute a solution. Here is one way to do that (though probably not the most efficient way).
Compute shortest paths between all pairs of vertices (using e.g. the Floyd-Warshall algorithm, in O(n^3) time for n vertices). Now, for every vertex pair (u, v), either d(u, v) = inf, indicating that there is no way to reach v from u at all, or not, indicating that there is some path from u to v. To answer the question "Does u # v hold?" (i.e., "Do u and v belong in the same component of the decomposition?"), we can simply calculate d(u, v) != inf || d(v, u) != inf.
This gives us a relation that we can use to build an undirected graph G' in which there is a vertex u' for each original vertex u, and an edge between two vertices u' and v' if and only if d(u, v) != inf || d(v, u) != inf. Intuitively, every connected component in this new graph must be a clique. This property can be checked in O(n^2) time by first performing a series of DFS traversals from each vertex to assign a component label to each vertex, and then checking that each pair of vertices belongs to the same component if and only if they are connected by an edge. If the property holds then the resulting cliques correspond to the desired decomposition; otherwise, there is no valid decomposition.
Interestingly, there are graphs that are not chains of strongly connected components (as claimed by Zotta), but which nonetheless do have transitive # relations. For example, a tournament is a digraph in which there is an edge, in some direction, between every pair of vertices -- so clearly # holds for every pair of vertices in such a graph. But if we number the vertices 1 to n and include only edges from lower-numbered to higher-numbered vertices, there will be no cycles, and thus the graph is not strongly connected (and if n > 2, then clearly it's not a path).
I'm quite surprised I couldn't find anything on this anywhere, it seems to be a problem that should be quite well known:
Consider the Euclidean shortest path problem, in two dimensions. Given a set of obstacle polygons P and two points a and b, we want to find the shortest path from a to b not intersecting the (interior of) any p in P.
To solve this, one can create the visibility graph for this problem, the graph whose nodes are the vertices of the elements of P, and where two nodes are connected if the straight line between them does not intersect any element of P. The edge weight for any such edge is simply the Euclidean distance between such two points. To solve this, one can then determine the shortest path from a to b in the graph, let's say with A*.
However, this is not a good approach. Creating the visibility graph in advance requires checking if any two vertices from any two polygons are connected, a check that has higher complexity than determining the distance between two nodes. So working with a modified version of A* that "does everything what it can before checking if two nodes are actually connected" actually speeds up the problem.
Still, A* and all other shortest path problems always start with an explicitly given graph for which adjacent vertices can be traversed cheaply. So my question is, is there a good (optimal?) algorithm for finding a shortest path between two nodes a and b in an "implicit graph" that minimizes checking if two nodes are connected?
Edit:
To clarify what I mean, this is an example of what I'm looking for:
Let V be a set, a, b elements of V. Suppose w: V x V -> D is a weighing function (to some linearly ordered set D) and c: V x V -> {true, false} returns true iff two elements of V are considered to be connected. Then the following algorithm finds the shortest path from a to b in V, i.e., returns a list [x_i | i < n] such that x_0 = a, x_{n-1} = b, and c(x_i, x_{i+1}) = true for all i < n - 1.
Let (V, E) be the complete graph with vertex set V.
do
Compute shortest path from a to b in (V, E) and put it in P = [p_0, ..., p_{n-1}]
if P = empty (there is no shortest path), return NoShortestPath
Let all_good = true
for i = 0 ... n - 2 do
if c(p_i, p_{i+1}) == false, remove edge (p_i, p_{i+1}) from E, set all_good = false and exit for loop
while all_good = false
For computing the shortest paths in the loop, one could use A* if an appropriate heuristic exists. Obviously this algorithm produces a shortest path from a to b.
Also, I suppose this algorithm is somehow optimal in calling c as rarely as possible. For its found shortest path, it must have ruled out all shorter paths that the function w would have allowed for.
But surely there is a better way?
Edit 2:
So I found a solution that works relatively well for what I'm trying to do: Using A*, when relaxing a node, instead of going through the neighbors and adding them to / updating them in the priority queue, I put all vertices into the priority queue, marked as hypothetical, together with hypothetical f and g values and the hypothetical parent. Then, when picking the next element from the priority queue, I check if the node's connection to its parent is actually given. If so, the node is progressed as normal, if not, it is discarded.
This greatly reduces the number of connectivity checks and improves performance for me a lot. But I'm sure there's still a more elegant way, in particular one where the "hypothetical new path" doesn't just extend by length one (parents are always actual, not hypothetical).
A* or Dijkstra's algorithm do not need an explicit graph to work, they actually only need:
source vertex (s)
A function next:V->2^V such that next(v)={u | there is an edge from v to u }
A function isGoal:V->{0,1} such that isGoal(v) = 1 iff v is a target node.
A weight function w:E->R such that w(u,v)= cost to move from u to v
And, of course, in addition A* is going to need a heuristic function h:V->R such that h(v) is the cost approximation.
With these functions, you can generate only the portion of the graph that is needed to find shortest path, on the fly.
In fact, A* algorithm is often used on infinite graphs (or huge graphs that do not fit in any existing storage) in artificial inteliigence problems using this approach.
The idea is, you only look on edges in A* from a given node (all (u,v) in E for some given u). You don't need the entire edges set E in order to do it, you can just use your next(u) function instead.
Given Graph G=(V,E) ,undirected and weightless, we would want to find the value of diameter D of graph G. Show how to find a value X such that X<=D<=2*X in running time of O(|V|+|E|).
Now, to find the actual diameter of graph you simply need to run BFS twice.Once from and arbitrary node and then from the most distend node. But in this question I need to find an approximation to the diameter. My guess was to run BFS once and choosing the largest distance as the diameter. There are two edge cases that can occur.
The first one occur when the chosen node is located on the perimeter of graph G. The distend node will be located on the opposite side of the perimeter and thus X will be equal to D.
The second case will occur when the chosen node is in the center of G and X will be equal to half of D( X in this case will be the radios of G).
This was my answer to this question. And yet I was given 15/25 . Is there an edge case that I didn't handle or was it wrong from the start?
Thank you in advance.
60% seems a bit harsh to this former algorithms TA -- you gave the correct algorithm and identified the extremal cases for the two inequalities. Nevertheless, I agree with amit that you needed to give a formal proof. If your graders are particularly strict, you might have needed to say a word or two as well about why your algorithm is linear-time.
Here's the start of a formal proof. Let d(v, w) be the minimum length of a path between vertices v and w. The diameter is defined to be D = max_{v, w} d(v, w). Your algorithm chooses an arbitrary vertex s and outputs X = max_{w} d(s, w).
You need to do a little bit of algebra to show two facts: that X <= D and that D <= 2 X. You'll need the triangle inequality d(a, b) + d(b, c) >= d(a, c), which holds for all vertices a, b, c, as well as the symmetry d(a, b) = d(b, a).
A directed graph is said to be uniquely connected if there exists exactly one path between every pair of vertices. How to identify whether a graph has this property or not? This needs to be done in order O(n+m), where n are the number of vertices of the graph and m are the edges.
It is quite clear that there shouldn't be any cross-edges or forward-edges in the graph. But what about back-edges?
If there is exactly one directed path between every pair of nodes, then
every node must have at least one out-edge (else no paths from that node to other nodes)
no node can have have more than one out-edge (if there is an edge from X to Y and an edge from X to Z, and there are paths from Y to T and from Z to T, then there are multiple paths from X to T)
But now, with every node having exactly one out-edge, and every node being reachable from every other node, the graph must be a single directed cycle.
That is trivial to check in O(n) time.
Edit: As Erik P notes in the comments, this argument only applies if the paths in question are simple paths. In the same spirit, a graph of size 3 may need special treatment, because the X-Y-Z-T reasoning above doesn't apply, which means a graph with nodes X,Y,Z and edges from X to Y and Z, and from Y and Z to X would be legal.