Find an O(n) algorithm that returns all interesting vertices of the graph - algorithm

Problem : A directed graph G with n vertices and a special vertex u is provided. We call a vertex v ‘interesting’ if there is a path from v to a vertex w such that there is a cycle containing the vertices w and u. Write an O(n) time algorithm which takes G (the whole graph) and the node u as input and returns all the interesting vertices.
Ineffiecient Algorithm : My idea initially was to consider the node u and compute all the cycles that contain u. (This itself seems like traversing through the nodes using DFS and then forward-tracking as well when you encounter a visited node) Now from each vertex on these cycles we can compute the number of nodes on the graph that do not belong to the cycle(s) but is connected with each particular vertex w not equal to u on a cycle. Add all these values to get the desired answer. This isn't an O(n) algorithm.

There are two cases:
If there are no cycles containing u, then no vertex can be "interesting".
If there are any cycles containing u, then a vertex v is "interesting" if and only if there's a path from v to u. (We don't need to worry about the w in the problem description, because if a cycle contains two vertices u and w, then any path that ends at u can be extended to end at w and vice versa.)
So, the most efficient algorithm would be as follows:
Using DFS, determine if u is in a cycle. (We don't need to find all cycles; we just need to determine whether there are any.)
Using DFS in the "reverse" direction, find all vertices from which u is reachable.
DFS requires O(|V| + |E|) time, which is greater than O(n) = O(|V|) unless |E| is in O(n); but then, there's no way to even read in the entire graph definition in less than |E| time, so this is unavoidable. Whoever gave you this question must not have really thought this through.

Related

An algorithm using Dijkstra to calculate

Given is a directed graph G = (V, E) with positive edge weights w:E to R+.
The graph represents roads in Brooklyn, and the weight on each edge indicates the length of the road in miles. A prize is placed in node t (in V). Given is a set of nodes A in V (A is a subset of V), and a function s:A to R+.
In each v in A there is a player. In the beginning of the game, all the players depart simultaneously and proceed towards the prize.
Every player proceeds in a shortest path from its origin node to t. The player that departs from node v proceeds at a constant speed s(v),
i.e., for every e in E, it takes this player w(e)/s(v) time-units to cross road e.
Suggest an efficient algorithm that returns the winner(s).
My attempt:
Algorithm:
Run Dijkstra on some node v in A, and initiate an array of size |A| (for each player).
For each v in A, iterate through a shortest path from v to t, and in each iteration add w(e)/s(v) to the sum of this specific node in the array.
Return the minimum of the array.
I think this can be improved, for example replace the array with other data structure which will make the last step more efficient, but I do not know how.
I will appreciate any help!
Thanks!
You can do this by running Dijkstra's algorithm once from the destination node t to compute all shortest paths to/from t. You're looking for the minimum, over all a ∈ A, of Distance(a, t) / Speed(a), where Distance is the standard sum-of-edge-weights from Dijkstra's algorithm. Since the original graph is directed, you'll need to reverse the direction of all edges first and work on that graph.
If 'A' is small, you can occasionally optimize this slightly by stopping Dijkstra's algorithm as soon as you've visited all of the nodes in A, although the worst-case runtime is the same.

algorithm to solve the replacement paths problem for specific situations

I have to solve this problem and it has been bugging me for hours and I can't seem to find a valid solution that satisfies the time complexity required.
For any edge e in any graph G, let G\e denote the graph obtained by deleting e from G.
(a)Suppose we are given an edge-weighted directed graph G in which the shortest path σ from vertex s to vertex t passes through every vertex of G. Describe an algorithm to compute the shortest-path distance from s to t in G\e, for every edge e of G, in O(VlogV) time. Your algorithm should output a set of E shortest-path distances,one for each edge of the input graph. You may assume that all edge weights are non-negative.[Hint: If we delete an edge of the original shortest path, how do the old and new shortest paths overlap?
(b) Describe an algorithm to solve the replacement paths problem for arbitrary undirected graphs in O(V log V ) time.
a) Consider the shortest path P between vertices s and t. Since P is a shortest path, there is no edge between any two vertices u and v in P in which the length of shortest path between u and v is bigger than 1 in the induced graph P. Since every vertex in G is present in P, So every edge of G is present in the induced graph of P. So we conclude that every edge in G is between two adjacent vertices in P (not the induced graph of P). The only thing you should check for each edge e which connects vertices u and v in G, is that there is another edge which connects u and v in G. If so, the shortest path doesn't change in G/e, otherwise s and t will lie on different components.
First of all I want to mention that the complexity can't only depend on V since the output should contain E values, therefore I guess it should be O(E + Vlog(V)).
I think the following idea should work for problem b) and thus for a) as well. Let σ be the shortest s-t path.
For every edge e in G/E(σ), the shortest path in G/e is still σ.
If we remove an edge e in σ, then the shortest path in the remaining graph would like this: it would start going along σ, then would continue outside (might be from the very first vertex s, then go back to σ (might be at the very last vertex t). Let's then iterate over all edges e=(u,v) that either go from G/σ to σ, or from one vertex of σ, that is closer to s, to another vertex of σ, that is closer to t, as edges of potential candidate paths for some shortest s-t path in G/e' for some e'. Suppose that w is the last vertex in the shortest s-u path U that belongs to σ. Then U+e+σ[v..t] is a potential candidate for a shortest s-t path in graphs G/e' for all e' in σ[w..v]. In order to efficiently store this candidate, we can use a Segment Tree data structure with min operation. This would give us O(E log(E)) total complexity for all updates after we consider all edges. It might be possible to make it O(Vlog(V)) if we look closer at the structure of the updates, but I am not sure at the moment, might be not. Precomputing vertices w for each shortest s-u path above can be done in a single Dijkstra run, if we already have σ.
So in the end the solution runs in O(Elog(E)) time. I am not sure how to make it O(E + Vlog(V)), it is possible to make Dijkstra to run in this time by using Fibonacci heap, but for the updates for candidates I don't really see a faster solution at the moment.

Is the worst time complexity of BFS in a graph traversal n+2E?

I understand that time complexity of BFS in a graph traversal is O( V + E ) since every vertex and every edge will be explored in the worst case.
Well,is the exact time complexity v+2E ??
Every vertex is explored once+ Every adjacent vertices
The sum of the degree of all the vertices in a graph= No of edges*2= 2E
Thus the time complexity is n+2E..Am i correct?
For a random graph, the time complexity is O(V+E): Breadth-first search
As stated in the link, according to the topology of your graph, O(E) may vary from O(V) (if your graph is acyclic) to O(V^2) (if all vertices are connected with each other).
Therefore the time complexity varies fromO(V + V) = O(V) to O(V + V^2) = O(V^2) according to the topology of your graph.
Besides, since |V| <= 2 |E|, then O(3E) = O(E) is also correct, but the bound is looser.
Assumptions
Let's assume that G is connected and undirected. If it's not connected, then you can apply the below idea to every connected component of G independently. In addition, let's assume that G is represented as an adjacency lists and for every vertex v, we can decide if v was visited in O(1) time for example using a lookup table.
Analyze
If you want to count the exact number of steps in the BFS you can observe that:
Since G is connected, BFS will visit every vertex exactly once, so we count |V| visits in nodes. Notice that in one visit you may perform more operations, not counting looping over edges, than just marking current vertex visited.
For every vertex v we want to count, how many edges the BFS examines at this vertex.
You have to loop over all edges of v to perform the BFS. If you skip one edge, then it's easy to show that BFS is not correct. So every edge is examined twice.
One question may arise here. Someone could ask, if there is a need to examine the edge (p, v) in vertex v, where p is the parent of v in already constructed BFS tree, i.e. we came to v directly from p. Of course you don't have to consider this edge, but deciding to skip this edge also costs at least one additional operation:
for (v, u) in v.edges:
if u == p: # p is the parent of v in already constructed tree
continue
if not visited[u]:
BFS(u, parent=v)
It examines the same number of edges that the code below, but has higher complexity, because for all but one edge, we run two if-statements rather than one.
for (v, u) in v.edges:
if not visited[u]: # if p is the parent of v, then p is already visited
BFS(u, parent=v)
Conclusion
You may even develop a different method to skip edge (v, p), but it always takes at least one operation, so it's a wasteful effort.

graph - The implementation of updating Minimum Spanning Tree after adding a new edge

Here is an excise
Suppose we are given the minimum spanning tree T of a given graph G
(with n vertices and m edges) and a new edge e = (u, v) of weight w
that we will add to G. Give an efficient algorithm to find the minimum
spanning tree of the graph G + e. Your algorithm should run in O(n)
time to receive full credit.
I have this idea:
In the MST, just find out the path between u and v. Then find the edge (along the path) with maximum weight; if the maximum weight is bigger than w, then remove that edge from the MST and add the new edge to the MST.
The tricky part is how to do this in O(n) time and it is also I get stuck.
The question is that how the MST is stored. In normal Prim's algorithm, the MST is stored as a parent array, i.e., each element is the parent of the according vertex.
So suppose the excise give me a parent array indicating the MST, how can I release the above algorithm in O(n)?
First, how can I identify the path between u and v from the parent array? I can have two ancestor arrays for u and v, then check on the common ancestor, then I can get the path, although in backwards. I think for this part, to find the common ancestor, at least I have to do it in O(n^2), right?
Then, we have the path. But we still need to find the weight of each edge along the path. Since I suppose the graph will use adjacency-list for Prim's algorithm, we have to do O(m) (m is the number of edges) to locate each weight of the edge.
...
So I don't see it is possible to do the algorithm in O(n). Am I wrong?
The idea you have is right. Note that, finding the path between u and v is O(n). I'll assume you have a parent array identifying the MST. tracking the path (for max edge) from u to v or u to root vertex should take only O(n). If you reach root vertex, just track the path from v to u or root vertex.
Now that you have the path from u -> u1 ... -> max_path_vert1 -> max_path_vert2 -> ... -> v, remove the edge max_path_vert1->max_path_vert2 (assuming this is greater than the added edge) and reverse the parents for u->...->max_path_vert1 and mark parent[u] = v.
Edit: More explanation for clarity
Note that, in MST there will be exactly one path between any pair of vertices. So, if you can trace from u->y and v->y, you have only traced through atmost n vertices. If you traced more than n vertices that means you visited a vertex twice, which will not happen in an MST. Ok, now hopefully you're convinced it's O(n) to track from u->y and v->y. Once you have these paths, you have established a path from u->v. Do you see how? I'm assuming this is an undirected graph, since finding MST for directed graph is a different concept in itself. For undirected graph, when you have a path from x->y you have a path from y-x. So, u->y->v exist. You don't even need to trace back from y->v, since weights for v->y will be same as that of y->v. Just find the edge with the maximum weight when you trace from u->y and v->y.
Now for finding edge weights in O(1); how are you storing your current weights? Adjacency list or adjacency matrix? For O(1) access, store it the way parent vertex array is stored. So, weight[v] = weight(v, parent[v]). So, you'll have O(1) access. Hope this helps.
Well - your solution is correct.
But regarding implementation, I dont see why you are using G instead of T to find the path between u and v. Using any search traversal in T for the path between u and v, will give you O(n). - That is, you can assume that v is the root and performs a Depth-First Search algorithm [in this case, you will have to assume all neighbors of v as children] - and stop the DFS once you find u - then, the nodes in the stack corresponds to the path between u and v.
It is easy afterward to find the cost of each edge in the path (O(n)), and it is easy as well to delete/add edges. In total O(n).
Does that help somehow ?
Or maybe you are getting O(n^2) - according to my understanding - because you access the children of a vertex v in T in O(n) -- Here, you have to present your data structure as a mapped array so that the cost is reduced to O(1). [for instace, {a,b,c,u,w}(vertices) -> {0,1,2,3,4}(indices of vertices).

minimum connected subgraph containing a given set of nodes

I have an unweighted, connected graph. I want to find a connected subgraph that definitely includes a certain set of nodes, and as few extras as possible. How could this be accomplished?
Just in case, I'll restate the question using more precise language. Let G(V,E) be an unweighted, undirected, connected graph. Let N be some subset of V. What's the best way to find the smallest connected subgraph G'(V',E') of G(V,E) such that N is a subset of V'?
Approximations are fine.
This is exactly the well-known NP-hard Steiner Tree problem. Without more details on what your instances look like, it's hard to give advice on an appropriate algorithm.
I can't think of an efficient algorithm to find the optimal solution, but assuming that your input graph is dense, the following might work well enough:
Convert your input graph G(V, E) to a weighted graph G'(N, D), where N is the subset of vertices you want to cover and D is distances (path lengths) between corresponding vertices in the original graph. This will "collapse" all vertices you don't need into edges.
Compute the minimum spanning tree for G'.
"Expand" the minimum spanning tree by the following procedure: for every edge d in the minimum spanning tree, take the corresponding path in graph G and add all vertices (including endpoints) on the path to the result set V' and all edges in the path to the result set E'.
This algorithm is easy to trip up to give suboptimal solutions. Example case: equilateral triangle where there are vertices at the corners, in midpoints of sides and in the middle of the triangle, and edges along the sides and from the corners to the middle of the triangle. To cover the corners it's enough to pick the single middle point of the triangle, but this algorithm might choose the sides. Nonetheless, if the graph is dense, it should work OK.
The easiest solutions will be the following:
a) based on mst:
- initially, all nodes of V are in V'
- build a minimum spanning tree of the graph G(V,E) - call it T.
- loop: for every leaf v in T that is not in N, delete v from V'.
- repeat loop until all leaves in T are in N.
b) another solution is the following - based on shortest paths tree.
- pick any node in N, call it v, let v be a root of a tree T = {v}.
- remove v from N.
loop:
1) select the shortest path from any node in T and any node in N. the shortest path p: {v, ... , u} where v is in T and u is in N.
2) every node in p is added to V'.
3) every node in p and in N is deleted from N.
--- repeat loop until N is empty.
At the beginning of the algorithm: compute all shortest paths in G using any known efficient algorithm.
Personally, I used this algorithm in one of my papers, but it is more suitable for distributed enviroments.
Let N be the set of nodes that we need to interconnect. We want to build a minimum connected dominating set of the graph G, and we want to give priority for nodes in N.
We give each node u a unique identifier id(u). We let w(u) = 0 if u is in N, otherwise w(1).
We create pair (w(u), id(u)) for each node u.
each node u builds a multiset relay node. That is, a set M(u) of 1-hop neigbhors such that each 2-hop neighbor is a neighbor to at least one node in M(u). [the minimum M(u), the better is the solution].
u is in V' if and only if:
u has the smallest pair (w(u), id(u)) among all its neighbors.
or u is selected in the M(v), where v is a 1-hop neighbor of u with the smallest (w(u),id(u)).
-- the trick when you execute this algorithm in a centralized manner is to be efficient in computing 2-hop neighbors. The best I could get from O(n^3) is to O(n^2.37) by matrix multiplication.
-- I really wish to know what is the approximation ration of this last solution.
I like this reference for heuristics of steiner tree:
The Steiner tree problem, Hwang Frank ; Richards Dana 1955- Winter Pawel 1952
You could try to do the following:
Creating a minimal vertex-cover for the desired nodes N.
Collapse these, possibly unconnected, sub-graphs into "large" nodes. That is, for each sub-graph, remove it from the graph, and replace it with a new node. Call this set of nodes N'.
Do a minimal vertex-cover of the nodes in N'.
"Unpack" the nodes in N'.
Not sure whether or not it gives you an approximation within some specific bound or so. You could perhaps even trick the algorithm to make some really stupid decisions.
As already pointed out, this is the Steiner tree problem in graphs. However, an important detail is that all edges should have weight 1. Because |V'| = |E'| + 1 for any Steiner tree (V',E'), this achieves exactly what you want.
For solving it, I would suggest the following Steiner tree solver (to be transparent: I am one of the developers):
https://scipjack.zib.de/
For graphs with a few thousand edges, you will usually get an optimal solution in less than 0.1 seconds.

Resources