Given an undirected graph G=(V,E) , V1,V2 are subsets of V.
d(V1,V2)=min d(v1,v2) ,
so I need to figure out how to find d(V1,V2) in O(|V|+|E|)
if then d(V1,V2)=0
otherwise, I randomly pick v1' from V1 and run BFS(V1,v1'), save the furthest vertex from v1'
at v1''
I will do the same for some random vertex v2' from V2.
return d(V1,V2)=min{ d(v1',v2'), d(v1',v2''),d(v1''v2'),d(v1'',v2'')}
will that work? since runtime of BFS is O(|V|+|E|) the suggested algorithm will run in O(|V|+|E|)
IMO what you can do is as follows:
Scan the set V1 and note all edges that begin at nodes in V1 and end at nodes not in V1.
Now combine all the nodes in V1 into one node. The edges noted in step 1 shall be the edges going out from this node.
Do the same for V2.
Now it reduces to the shortest route problem between node V1 and V2. This can be solved by conducting a simple BFS on node V1 or V2 in O(E) where E is the number of edges in the graph.
Related
The following is the question I am working on:
Consider a directed, weighted graph
G
where all edge weights are
positive. The goal of this problem is to find the shortest path
in
G
between two pre-specified vertices
s
and
t
, but with an added twist: you are allowed to change the weight
of
exactly
one edge (of your
choosing) to zero.
In other words, you must pick an edge in
G
to set to zero that minimizes the shortest
path between
s
and
t
.
Give an efficient algorithm to achieve this goal in
O
(
E
lg
V
) time and analyze your algorithm’s running
time. Sub-optimal solutions will receive less credit.
Hint:
You may have to reverse the edges, run a
familiar algorithm a number of times, plus do some extra work
So I have tried running Dijkstra's from s to all other nodes and then I have tried reversing the edges and running it again from s to all other nodes. However, I found out that we have to run Dijskstra's from s to all other nodes and then reverse the edges and then run Dijkstra's from all other nodes to t. I am not exactly sure how this helps us to find the edge to set to zero. By my intuition I thought that we would simply set the maximum weight edge to zero. What is the point of reversing the edges?
We need to run Dijkstra's algorithm twice - once for the original graph with s as the source vertex, and once with the reversed graph and t as the source vertex. We'll denote the distance we get between vertex s and i from the first run as D(i) and the distance we get between vertex t and i second run D_rev(i).
Note that we can go follow the reversed edges backwards (i.e., follow them in the original direction), thus D_rev(i) is actually the shortest distance from vertex i to t. Similarly, D(i) is the shortest distance from vertex s to i following Dijkstra's algorithm.
We can now loop through all the edges, and for each edge e which connects v1 and v2, add up D(v1) and D_rev(v2), which corresponds to the weight of the path s -> v1 -> v2 -> t with e being the zero edge, since we can go from s to v1 with a distance of D(v1), set e to 0, go from v1 to v2, and then go from v2 to t with a distance of D_rev(v2). The minimum over these is the answer.
A rough proof sketch (and also a restatement) : if we set an edge e to 0, but don't use it in the path, we can be better off setting an edge that's in the path to 0. Thus, we need only consider paths that includes the zeroed edge. The shortest path through a zeroed edge e is to first take the shortest path from s to v1, and then take the shortest path from v2 to t, which are exactly what were computed using the Dijkstra algorithm, i.e., D and D_rev.
Hope this answer helps!
A directed graph G = (V, E) is said to be semi-connected if, for all pairs of vertices u, v in V we have u -> v or v-> u path.
Give an efficient algorithm to determine whether or not G is semi-connected
Trivial O(V^3) solution could be to use floyd warshal all-to-all shortest path, but that's an overkill (in terms of time complexity).
It can be done in O(V+E).
Claim:
A DAG is semi connected in a topological sort, for each i, there there is an edge (vi,vi+1)
Proof:
Given a DAG with topological sort v1,v2,...,vn:
If there is no edge (vi,v(i+1)) for some i, then there is also no path (v(i+1),vi) (because it's a topological sort of a DAG), and the graph is not semi connected.
If for every i there is an edge (vi,vi+1), then for each i,j (i < j) there is a path vi->vi+1->...->vj-1->vj, and the graph is semi connected.
From this we can get the algorithm:
Find Maximal SCCs in the graph.
Build the SCC graph G'=(U,E') such that U is a set of SCCs. E'= { (V1,V2) | there is v1 in V1 and v2 in V2 such that (v1,v2) is in E }.
Do topological sort on G'.
Check if for every i, there is edge Vi,V(i+1).
Correctness proof:
If the graph is semi connected, for a pair (v1,v2), such that there is a path v1->...->v2 - Let V1, V2 be their SCCs. There is a path from V1 to V2, and thus also from v1 to v2, since all nodes in V1 and V2 are strongly connected.
If the algorithm yielded true, then for any two given nodes v1, v2 - we know they are in SCC V1 and V2. There is a path from V1 to V2 (without loss of generality), and thus also from v1 to v2.
As a side note, also every semi-connected graph has a root (vertex r that leads to all vertices):
Proof:
Assume there is no root. Define #(v) = |{u | there is a path from v to u}| (number of nodes that has a path from v to them).
Choose a such that #(a) = max{#(v) | for all v}.
a is not a root, so there is some node u that has no path from a to it. Since graph is semi connected, it means there is a path u->...->a. But that means #(u) >= #(a) + 1 (all nodes reachable from a and also u).
Contradiction to maximality of #(a), thus there is a root.
Amit's soltuin described completely the most efficient approach. I might just add that one can replace step 4 by checking whether there exists more than one topological order of G'. If yes, then the graph is not semi connected. Otherwise, the graph is semi connected. This can be easily incorporated in Kahn's algorithm for finding topological order of a graph.
Another less efficient solution that works in quadratic time is the following.
First, construct another graph G* which is the reverse of the original graph. Then for each vertex v of G, you run a DFS from v in G and consider the set of reachable nodes as R_v. If R_v != V(G), then run another DFS from v in G* and let the set of reachable nodes be R_v. If the union of R_v and R_v is not V(G) then the graph is not semi connected.
The main idea behind step 3 and 4 of Amit's algorithms is to check whether your depth-first forest is comprised of multiple depth-first trees. Presence of a single tree is a necessary condition for semi-connectivity as multiple trees represent unconnected nodes.
Similar ideas: Hamiltonian path, Longest path length
I am learning minimum spanning tree. I go through Prim's algorithm for weighted directed graph.
Algorithm is simple
you have two set of vertices, visited and non-visited
set distance for all edges to infinity
start with any vertex in non-visited set and explore its edges
In all edges, update distance of the destination vertex with the weight of the edge if destination vertex it is not visited and if weight of the edge is less than the distance of destination vertex
pick the non-visited vertex with smallest distance and do it again until all vertex are visited
I believe with above algorithm, I will be able to find the spanning tree having minimum cost among all spanning trees, i.e. Minimum spanning tree.
But I applied it to the following example and I think it is failed.
Consider following example
Vertices are {v1,v2,v3,v4,v5} and edges with weight (x,y) : w =>
(v1,v2) : 8
(v1,v3) : 15
(v1,v4) : 7
(v2,v5) : 4
(v4,v5) : 7
First I explore v1, it has edges to v2,v3,v4 so graph become
Vertex v1 is visited and (vertex, distance) =>
(v2,8)
(v3,15)
(v4,7)
Now v4 has the least distance i.e. 7 so I explore v4, it has edge to v5 so following modification occur
Vertex v4 is visited and (vertex, distance) => (v5,7)
Now among all v5 is having the least distance , i.e. 7 , so I explore v5 and it does not have any edge so I just mark it visited
Vertex v5 is visited
Now, confusion starts from here
The vertex with the least distance is now v2, it has edge to v5 with the weight 4 and currently v5 having distance is 7, previously assigned by the edge (v4,v5) : 7 , so, I believe that to make minimum spanning tree, distance for v5 should be updated from 7 to 4 as 4 < 7 but it will not because v5 has already been visited and Prim's Algorithm do not update the distance of the vertex that already been visited and distance for v5 will remain 7 instead of 4 and this tree will not have minimum cost
Do I get it right ? or am I doing any mistake ?
Thanks
First I should mention that Prim's algorithm is just applicable to undirected graphs so if we consider the graph is undirected, this is the step by step progress of the algorithm on your case:
And you should consider that finding a minimum spanning tree is not even possible many times in the directed graphs, nevertheless the closest notion to MST for directed graphs is minimum cost arborescence.
I was searching for an algorithm that could find a very basic (i.e. the shortest) cycle that includes a given vertex.
In other words, if a vertex v1 participates in two cycles say one with v1, v2, v3 and the other v1, v2, v4, v5, v6. I want the algorithm to give me v1, v2, v3 cycle as the output.
Does anyone know which algorithm would do that?
Also, what could be the complexity of this algorithm.
Thanks in advance.
Start a bfs from the given vertex v0. Stop as soon as bfs considers a vertex v1 adjacent to v0, and v0 is not parent of v1 in bfs tree. The found path from v0 to v1 plus (v1,v0) edge is your shortest cycle. Complexity is O(n+m) due to bfs.
Say we have a strongly connected directed graph G (V,E) with positive edge weights and V0 belongs to V. Write an algorithm to find the shortest paths between all pairs of nodes through V0
An interview question. Clearly we could use Bellman-Ford which takes O(VE).
However there must exist a better solution. Any help please?
I think you could even use Dijkstra's algorithm. Run it once to find the shortest paths from V0 to all other vertices and then once more to find the shortest path from every other vertex to V0 (this is the same as running regular Dijkstra on the graph with reversed edges). Then for any pair (V1,V2) concatenate paths from V1 to V0 and from V0 to V2.