Find all pairs of nodes whose deletion disconnects graph - algorithm

Given undirected, connected graph, find all pairs of nodes (connected by an edge) whose deletion disconnects the graph.
No parallel edges and no edges connecting node to itself.
The problem seems similar to finding articulation points (or bridges) of a connected, undirected graph - yet with a twist, that we have to remove a pair of vertices connected by an edge (and all other edges connected to that pair).
This is a homework question. I've been trying to solve it, read about DFS and articulation points algorithms (that bookkeap depth and lowpoint of each node) - but none of these approaches help this particular problem. I've checked through Cormen's Intro to Algorithms, but no topic suggested itself as appropriate (granted, book does have 1500 pages).
While it's true that finding articulation point would also (most of the time) find such a pair, there are a lot of pairs that are not articulation points - consider a graph with 4-vertices,5-edges (square with a single diagonal): it has one such pair but no articulation points (nor bridges).
I'm lost. Help me, stack overflow, you are my only hope.

Rather straightforward, maybe not the most efficient:
Let the graph be G=(V,E) with V := {v_1, ..., v_n}. For each subset V' of V let G_V' be the node induced subgraph comprising the nodes V \ V'. Let further N>_v_i := {v_j in V : {v_i,v_j} in E and j > i} be the set of all neighbors of v_i in G with index greater than i. Finally, let c(G) be the set of connected components of a graph.
Compute the pairs as follows:
pairs = {}
for each v in V:
compute G_{v}
if G_{v} is unconnected:
for each v' in N>_v:
# Ensures that removal of v' does not render subgraph connected
# (Note comment by MkjG)
if |c(G_{v})| > 2 or {v'} not in c(G_{v}):
add {v,v'} to pairs
else:
for each v' in N>_v:
compute G_{v,v'}
if G_{v,v'} unconnected:
add {v,v'} to pairs
Connectivity can be checked via DFS or BFS in O(m+n). The runtime should hence be O(n * k * (m+n)), where k is the maximum degree of G.

Update to my previous answer based on the suggestion by #MkjG to use DFS for computing articulation points.
Let the graph be G=(V,E) with V := {v_1, ..., v_n}_. For each subset V' of V let G_V' be the node induced subgraph comprising the nodes V \ V'. For G connected, we call v in V an articulation point if G_{v} is unconnected. Let N_v be the set of neighbors of v in G.
Articulation points can be computed via DFS, read here for more information on the algorithm. In short:
compute a DFS tree T for some root node r in V
r is an articulation point, iff it has more than one child in T
any other node v in V is an articulation point, iff it has a child v' in T that satisfies the following condition: no node in the subtree T' of T rooted at v' has a back edge to an ancestor of v
Let the result of a DFS on graph G be a function c on the nodes v in V. c(v) is a subset of N_v, it holds v' in c(v) iff both of the following conditions are met:
v' is a child of v in T
no node in the subtree T' of T rooted at v' has a back edge to an ancestor of v
Note that for the root node r of T, c(r) is the set of all children of r. Function c can be computed in time O(n+m).
Compute the separator pairs as follows:
# performs DFS on G for some root node r
c = DFS(G,r)
# computes articulation points of G and corresponding number of components
aps = {}
compCounts = {}
for each v in V:
numComps = |c(v)|
if v != r:
++numComps
if numComps > 1:
add v to aps
compCounts[v] = numComps
# computes the set of all separator pairs containing at least on ap
S = {}
for each v in aps:
numComps = compCounts[v]
for each v' in N_v:
if numComps > 2:
# G_{v,v'} has at least two connected components
add {v,v'} to S
else:
# if v' is an isolated node in G_{v}, then G_{v,v'} is connected
if N_v' != {v}:
add {v,v'} to S
# computes remaining separator pairs
for each v in V \ aps:
compute G_{v}
# performs DFS on G_{v} for some root r_v != v
c_v = DFS(G_{v},r_v)
# adds separator pairs for articulation points of G_{v} in N_v
for each v' in N_v:
numComps = |c(v')|
if v' != r_v:
++numComps
if numComps > 1:
add{v,v'} to S
Runtime is in O(n * (n+m))

A set of k edges disconnecting a graph is called a k-cut. You are trying to enumerate all 2-cuts of a graph.
This paper describes an efficient algorithm to enumerate all cuts of a graph. It should be possible to adapt it to find all 2-cuts of a graph.

Related

Construct an efficient, minimum spanning tree such that given subset of vertices in G are leaves + proof

I am trying to design an algorithm where, given a connected weighted graph G = (V, E) and a subset of vertices U that is in V, will construct a minimum spanning tree such that all vertices in U are leaves (other vertices may also be leaves), or returns that no such tree exists (False).
This is all I got, adapting Prim's algorithm (fair warning, its really bad; don't even know if it works/is efficient or what data structures to use, I will accept literally any other correct algorithm instead):
Let x be an arbitrary node in G
Set S = {x}
While S != V:
Let (u,v) be the cheapest edge with u in S and v not in S
Add (u,v) to tree T if u is not in U, add v to S
If all u in U is in the tree T:
return T
Else:
return False
I also have a picture of what I think it would do to this graph I drew:
pic here
A proof that the algorithm is correct would also give me some peace of mind.
If all vertices u āˆˆ U are to be leaves in a solution, no u can be used in that solution to connect two other vertices. All vertices not in U must be connected by edges not incident to any u.
Remove U and all edges incident to U. Find the minimum spanning tree, then connect each u to the tree by the smallest-weighted edge available from those we removed.

Minimum Spanning Tree Graph

I have a connected graph G=(V,E) V={1,2,...,n} and a cost function c:E->R
and a second partial graph G'=(V,T) where T={ for every vertex vāˆˆ V find the neighbor with the minimum cost and add the new edge to T}
If G' graph has at least 2 connected components with the set of vertices we consider the graph H where
iff the set of edges (from the initial graph G) is not null.We define over the edges of H a cost function.
Let's say I choose V(H)={a,e,f} and E(H)={ae,af,fe} and
E12={ab,bc,bd,ed}
E23={eg,ef} E31={fc,fd}
c'(ae)=min{c(ab),c(bc),c(bd),c(ed)}=4
c'(af)=min{c(fc),c(fd)}=9
c'(fe)=min{c(eg),c(ef)}=8
Now for every edge e āˆˆ E(H) we note with e' the edge (from the original graph G)
for which this minimum is attained.
So e'={bc,df,eg} because bc=4 , df=9 and eg=8 and are the min edges that connect my components.
And I have a minimum spanning tree in H relative to the cost function c' and A' is the set of edges for this tree.
So A'={ae,fe} (I deleted the edge with the maximum cost=af from my graph H to create a min spanning tree)
and I have another set of edges A'={e'|eāˆˆA'} and
is a min spanning tree in G relative to the function cost c.
But none of my edges from A' are the same with the ones from e'.
What I'm I doing wrong?
Looks like you're implementing Boruvka's algorithm. If you look at the notation, it says there's an edge from one new node vC1 to a new node vC2 if there are a pair of nodes x ∈ C1 and y ∈ C2 that are adjacentnin the original graph G. In other words, there's an edge between two new nodes if the connected components they correspond to in G' are adjacent in G. The cost of the edge running between them is then the lowest of the costs of any of the edges running between those CC's in the original graph G.

Algorithm for finding weight of path with lowest weight in weighted directed graph

I am given a G=(V,E) directed graph, and all of its edges have weight of either "0" or "1".
I'm given a vertex named "A" in the graph, and for each v in V, i need to find the weight of the path from A to v which has the lowest weight in time O(V+E).
I have to use only BFS or DFS (although this is probably a BFS problem).
I though about making a new graph where vertices that have an edge of 0 between them are united and then run BFS on it, but that would ruin the graph direction (this would work if the graph was undirected or the weights were {2,1} and for an edge of 2 i would create a new vertex).
I would appreciate any help.
Thanks
I think it can be done with a combination of DFS and BFS.
In the original BFS for an unweighted graph, we have the invariant that the distance of nodes unexplored have a greater or equal distance to those nodes explored.
In our BFS, for each node we first do DFS through all 0 weighted edges, mark down the distance, and mark it as explored. Then we can continue the other nodes in our BFS.
Array Seen[] = false
Empty queue Q
E' = {(a, b) | (a, b) = 0 and (a, b) is of E}
DFS(V, E', u)
for each v is adjacent to u in E' // (u, v) has an edge weighted 0
if Seen[v] = false
v.dist = u.dist
DFS(V, E', v)
Seen[u] = true
Enqueue(Q, u)
BFS(V, E, source)
Enqueue(Q, source)
source.dist = 0
DFS(V, E', source)
while (Q is not empty)
u = Dequeue(Q)
for each v is adjacent to u in E
if Seen[v] = false
v.dist = u.dist + 1
Enqueue(Q, v)
Seen[u] = true
After running the BFS, it can give you all shortest distance from the node source. If you only want a shortest distance to a single node, simply terminate when you see the destination node. And yes, it meets the requirement of O(V+E) time complexity.
This problem can be modified to the problem of Single Source Shortest Path.
You just need to reverse all the edge directions and find the minimum distance of each vertex v from the vertex A.
It could be easily observed that if in the initial graph if we had a minimal path from some vertex v to A, after changing the edge directions we would have the same minimal path from A to v.
This could be simply done either by Dijkstra OR as the edges just have two values {0 and 1}, it could also be done by modified BFS (first go to vertexes with distance 0, then 1, then 2 and so on.).

How to update MST from the old MST if one edge is deleted

I am studying algorithms, and I have seen an exercise like this
I can overcome this problem with exponential time but. I don't know how to prove this linear time O(E+V)
I will appreciate any help.
Let G be the graph where the minimum spanning tree T is embedded; let A and B be the two trees remaining after (u,v) is removed from T.
Premise P: Select minimum weight edge (x,y) from G - (u,v) that reconnects A and B. Then T' = A + B + (x,y) is a MST of G - (u,v).
Proof of P: It's obvious that T' is a tree. Suppose it were not minimum. Then there would be a MST - call it M - of smaller weight. And either M contains (x,y), or it doesn't.
If M contains (x,y), then it must have the form A' + B' + (x,y) where A' and B' are minimum weight trees that span the same vertices as A and B. These can't have weight smaller than A and B, otherwise T would not have been an MST. So M is not smaller than T' after all, a contradiction; M can't exist.
If M does not contain (x,y), then there is some other path P from x to y in M. One or more edges of P pass from a vertex in A to another in B. Call such an edge c. Now, c has weight at least that of (x,y), else we would have picked it instead of (x,y) to form T'. Note P+(x,y) is a cycle. Consequently, M - c + (x,y) is also a spanning tree. If c were of greater weight than (x,y) then this new tree would have smaller weight than M. This contradicts the assumption that M is a MST. Again M can't exist.
Since in either case, M can't exist, T' must be a MST. QED
Algorithm
Traverse A and color all its vertices Red. Similarly label B's vertices Blue. Now traverse the edge list of G - (u,v) to find a minimum weight edge connecting a Red vertex with a Blue. The new MST is this edge plus A and B.
When you remove one of the edges then the MST breaks into two parts, lets call them a and b, so what you can do is iterate over all vertices from the part a and look for all adjacent edges, if any of the edges forms a link between the part a and part b you have found the new MST.
Pseudocode :
for(all vertices in part a){
u = current vertex;
for(all adjacent edges of u){
v = adjacent vertex of u for the current edge
if(u and v belong to different part of the MST) found new MST;
}
}
Complexity is O(V + E)
Note : You can keep a simple array to check if vertex is in part a of the MST or part b.
Also note that in order to get the O(V + E) complexity, you need to have an adjacency list representation of the graph.
Let's say you have graph G' after removing the edge. G' consists have two connected components.
Let each node in the graph have a componentID. Set the componentID for all the nodes based on which component they belong to. This can be done with a simple BFS for example on G'. This is an O(V) operation as G' only has V nodes and V-2 edges.
Once all the nodes have been flagged, iterate over all unused edges and find the one with the least weight that connects the two components (componentIDs of the two nodes will be different). This is an O(E) operation.
Thus the total runtime is O(V+E).

Merge most of the black vertices of DAG together so that it remains DAG?

I have a DAG ( Directed Acyclic Graph ) with vertices having any of the 2 colours black or white. I need to merge as many black vertices together with the constraint that the graph should remain acyclic. Hence the final DAG should have minimum no. of black vertices. What is the best algorithm for this problem?
Here is one possible strategy. It reduces your problem to a colouring problem (which you can then use established heuristics algorithm from literature to solve).
Call the DAG G = (V,E) where V is the set of vertices. Let B be the set of black vertices and W be the set of white vertices. We want to construct a new simple graph G' = (B,E'). We construct it as follow:
algorithm contruct G' input: G
Let G' be a graph with vertex set B and no edges
for any pair of vertices v and v' where v,v' in B:
Let (G'', v'') = merge (v,v',G)
#comment: here, we let G'' to be the graph resulted from merging v and v'
#also, let's assume that v and v' merge to become v''
if detect_cycle(G'',v'') = true:
add edge (v,v') into G'
output G'
algorithm detect_cycle(G,v):
do BFS in G starting at v, with the modification when reaching any vertex v':
if v is connected to v': return true
return false
Note that G' is a simple graph and not a DAG and when doing BFS on G, you cannot go against the direction of an edge in G.
Essentially, we try to build G' with the set of black vertices in G such that if two vertices v adjacent to v' in G', then merging them causes cyclic graph in G. If v is not adjacent to v' in G' then it's safe to merge them. The problem then got reduced to find the minimum number of colors required to vertex-color G'. For background on vertex colouring, check out this link: https://en.wikipedia.org/wiki/Graph_coloring#Vertex_coloring. Basically vertex coloring is about finding the minimum number of sets where in each set, you can put in pairwise-nonadjacent vertices, then assign a label (or color) to each set (every vertex in the same set get the same label). Every black vertex with the same label in G' could be merged in G.
Heuristic algorithms for graph colouring could be found here:
http://heuristicswiki.wikispaces.com/Graph+coloring
and here: http://heuristicswiki.wikispaces.com/Degree+based+ordering
I hope it helps. Let me know if you find a better solution or a bug in the above solution.
Let the graph be G = (V,E)
Topological sort the graph to get the list of vertices = L(V).
L(B) = list of black vertices extracted from L(V) with the order maintained.
Let n = no. of vertices in L(B).
Let DVA = empty array of deleted vertices of size n initialized with 0.
for i = vertices 1 to n in L(B)
if(DVA[i] == 1)
continue;
for j = vertices i+1 to n in L(B)
if(DVA[j] == 1)
continue;
if(detect_cycle(G, i, j) == 0) //merging i and j will not create cycle
Merge j to i in G;
DVA[j] = 1;
This algorithm works on the fact that topological order of black vertices do not change while merging 2 vertices (except for these 2 vertices) .
I guess this method will produce fairly good result, but I am not sure whether it will produce the optimal result of having least no. of black vertices.

Resources