Given a general undirected graph, how can we print all the biconnected components of the graph in O(N+M) time? I know Tarjan's algorithm that is used to output all the articulation points of an undirected graph but I am finding it hard to extend the algorithm to print the biconnected components. I tried searching google but all the results that I got are not working on my test cases as they miss out on edge cases of the algorithm.
Can someone please provide working code for this problem.
Def: A biconnected component is a connected subgraph containing no vertex whose deletion would disconnect the subgraph.
Edit: I have successfully implemented the algorithm as described in this link provided by Niklas. Now I have a different question, how can I find out sub graphs of an undirected graph containing no edge whose deletion would disconnect the subgraph. Please help me solve this alternate problem as well.
It's a classical problem with a known linear-time algorithm. You will probably need to decompose the graph into connected components first, though. Algorithm description from Wikipedia:
The classic sequential algorithm for computing biconnected components
in a connected undirected graph due to John Hopcroft andRobert
Tarjan (1973) [1] runs in linear time, and is based on depth-first
search. This algorithm is also outlined as Problem 22-2 of Introduction
to Algorithms (both 2nd and 3rd editions). The idea is to run a
depth-first search while maintaining the following information:
the depth of each vertex in the depth-first-search tree (once it gets
visited), and for each vertex v, the lowest depth of neighbors of all
descendants of v in the depth-first-search tree, called
the lowpoint. The depth is standard to maintain during a depth-first
search. The lowpoint of v can be computed after visiting all
descendants of v (i.e., just before v gets popped off the
depth-first-search stack) as the minimum of the depth of v, the depth
of all neighbors of v (other than the parent of v in the
depth-first-search tree) and the lowpoint of all children of v in the
depth-first-search tree. The key fact is that a nonroot vertex v is a
cut vertex (or articulation point) separating two biconnected
components if and only if there is a child y of v such that
lowpoint(y) ≥ depth(v). This property can be tested once the
depth-first search returned from every child of v (i.e., just
before v gets popped off the depth-first-search stack), and if
true, v separates the graph into different biconnected components.
This can be represented by computing one biconnected component out of
every such y (a component which contains y will contain the subtree
of y, plus v), and then erasing the subtree of y from the tree.The
root vertex must be handled separately: it is a cut vertex if and only
if it has at least two children. Thus, it suffices to simply build one
component out of each child subtree of the root (including the root).
A good pseudo-code implementation can be found at http://www.cs.umd.edu/class/fall2005/cmsc451/biconcomps.pdf.
Have a look at this PhD thesis on Planarity Testing by Path Addition.
Chapter 5 gives pseudo code for a DFS algorithm (two versions using recursion or iteration) and an algorithm to partition (decompose) the DFS tree (also known as a Tremaux tree) into a hierarchy of path segments (or chains). Chapter 4 gives a classification of these path segments into 4 different types depending on where the tail of the path segment connects in the DFS tree (relative to the path segment's head).
Given this separation, you can partition the tree into biconnected components such that:
Class 1 path segments are not part of any biconnected component;
Class 2 (minus the edges & vertices succeeding the segment's head and preceding the tail which, like Class 1 segments, are not part of any biconnected component) and Class 3 path segments form a loop and are at the start (root) of a biconnected component; and
Class 4 segments are part of a biconnected component which contains their most recent Class 2 or 3 ancestor path segment.
If correctly done, you should be able to extract these biconnected components in O(V+E) time.
There is Java source code at the back of the thesis which does a full planarity test in O(V+E) time & memory which may give you some further pointers (and extracts all permutations P of embeddings of the biconnected components in O(P(V+E))).
Related
I’m familiar with the Hamilton path for a directed graph - visit every node exactly once.
I’m looking for an algorithm to walk the graph so that I visit every node at least once. I can’t find the standard name for this problem, if any.
This graph is walkable - root-a-d-b-c
This graph is not walkable - because in my walk, if I reach c, I have no directed edge to reach a & d and conversely, if I walk to a, d; there’s no directed edge that takes me to b & c
Hope that clarifies the question? Is there a standard name for this type of graph walk and an algorithm to solve it?
Hamiltonian path
Finding at most 2 leafs in the graph
I don't know if there's a name for a directed "walkable" graph, but it's not too hard to determine of a graph is walkable or not:
Find all the strongly connected components using Tarjan's algorithn, for example
Make a new directed graph of the connections between SCCs. This will be a DAG, and your original graph is walkable if and only if this DAG is walkable.
To determine whether or not a DAG is walkable, do a topological sort. Then check that each vertex has an edge to the next.
Each of these steps takes linear time, so you get O(|V|+|E|) complexity for the whole algorithm.
Theorem: a directed graph is walkable if and only if its strongly connected components are totally ordered by reachability.
Proof sketch: (walkable implies condition) The existence of a walk implies that, for each two strongly connected components, a vertex from one or the other appears first in the walk. That component can reach the other. (condition implies walkable) Since there is full connectivity inside a strongly connected component, each is walkable on its own. We just have to concatenate the walks according to the total order, adding the necessary transitions.
The proof is constructive, so we can extract an algorithm.
Algorithm
Compute the strongly connected components.
Concatenate the strongly connected components in topological order. Actually Tarjan's algorithm will list them in reverse topological order, so this doesn't need to be a separate step.
For each adjacent pair in the previous list, use breadth-first search to find a shortest path.
In general, this algorithm does not find the shortest walk (that's NP-hard by reduction from Hamiltonian path).
I'm doing some practice for an upcoming interview, and a practice question I found asks for an O(V+E) algorithm to tell if a graph is biconnected. This page from Princeton says that a graph is biconnected if it has no articulation vertices, where an articulation vertex is a vertex whose removal will increase the number of connected components (since a biconnected graph should have one connected component).
One common solution to this problem is to do DFS with additional tracking to see if any of the vertices are articulation vertices. This page says that a vertex is an articulation vertex if
V is a root node with at least 2 children
OR
V has a child that cannot reach an ancestor of V
However, the condition for root nodes doesn't make sense to me. Here is an example of a biconnected graph:
If we choose any of the nodes to be the root, they ALL have 2 or more children, so would be an articulation vertex thus making the graph not biconnected. This is a common algorithm for finding connected components, so assume I have misunderstood something. What do I actually need to check for the root node to see if a graph is biconnected?
You're supposed to do depth-first search, which means that the DFS tree always looks like
1 4
| |
2---3
because you can't explore the 1--4 link until you're done exploring everything that can be reached from 2 without going through 1, and you won't add 1--4 because it makes a cycle with the tree edges. No node in this tree has two children (1 is the root).
I have a graph and a starting node. I want to find how many nodes become isolated when I remove each node in the graph, for all nodes, using DFS.
For example, if I start on a fixed node 1, and remove node 2, how many isolated nodes I will have? and if I remove node 3?
I know I can just do DFS for all nodes(removing a different node each time), but doing so I will have to navigate the graph one time for each node, I want to solve it with just one run.
I have been told it has O(|V|*||A|), being |V|=number of edges, and |A|= number of nodes.
I've been playing with prenum and postnums, but with no success.
Let N be the number of vertices and M be the number of edges. If you just want a O(NM) solution as you stated, you don't need to go any further than running a DFS for each vertex.
The complexity for each DFS is O(N+M) so the total complexity will be of O(N(N+M)) = O(N²+NM). Usually we have more edges than vertices, so NM grows much faster than N² and we can say that the complexity is of O(NM). Keep in mind, though, that if you physically delete the current vertex at each step your implementation will have a much worse complexity, because physically deleting a vertex means removing entries from a lot of adjacency lists, which is costly no matter how you represent the graph. There is an implementation trick to speed up the process: instead of physically deleting the current vertex before each DFS, just mark the vertex as deleted, and when you are going through the adjacency lists during the DFS just ignore the marked vertex.
However, i feel that you can solve this problem in O(N+M) using Tarjan's algorithm for finding articulation points. This algorithm will find every vertex that, when removed from the graph, splits the graph in more than one connected component (these vertices are called articulation points). It's easy to see that there won't be isolated vertices if you remove a vertex that is not an articulation point. However, if you remove an articulation point, you will split the graph in two parts G and G', where G is the connected component of the starting vertex, and G' is the rest of the graph. All vertices from G' are isolated because you can't reach them if you run a DFS from the starting vertex. I think that you can find the size of G' for each vertex deletion efficiently, maybe you can even do this while running Tarjan's. If i find a solution i can edit this answer later.
EDIT: i managed to solve the problem in O(N+M). I will give some hints so you can find the answer by yourself:
Every undirected graph can be decomposed in (not disjoint) sets of biconnected components: each biconnected component is a subset of the vertices of the graph where every vertex in this subset will remain connected even if you remove any vertex of the graph
Tarjan's O(N+M) algorithm to find bridges and articulation points can be altered in order to find the biconnected components, finding which vertices belong to each biconnected component, or which biconnected components contain each vertex
If you remove any vertex that is not an articulation point, answer for this vertex is obviously N-1
If you remove an articulation point, every vertex in the same biconnected component of the starting vertex will still be acessible, but you don't know about the other biconnected components. Don't worry, there is a way to find this efficiently
You can compress every graph G in a graph B of its biconnected components. The compression algorithm is simple: every biconnected component becomes a vertex in B, and you link biconnected components that share some articulation point. We can prove that the resulting graph B is a tree. You must use this tree somehow in order to solve the problem presented in step 4
Good luck!
Although we can check a if a graph is bipartite using BFS and DFS (2 coloring ) on any given undirected graph, Same implementation may not work for the directed graph.
So for testing same on directed graph , Am building a new undirected graph G2 using my source graph G1, such that for every edge E[u -> v] am adding an edge [u,v] in G2.
So by applying a 2 coloring BFS I can now find if G2 is bipartite or not.
and same applies for the G1 since these two are structurally same. But this method is costly as am using extra space for graph. Though this will suffice my purpose as of now, I'd like know if there any better implementations for the same.
Thanks In advance.
You can execute the algorithm to find the 2-partition of an undirected graph on a directed graph as well, you just need a little twist. (BTW, in the algorithm below I assume that you will eventually find a 2-coloring. If not, then you will run into a node that is already colored and you find you need to color it to the other color. Then you just exit saying it's not bipartite.)
Start from any node and do the 2-coloring by traversing the edges. If you have traversed every edge and every node in the graph then you have your partition. If not, then you have a component that is 2-colored and there are no edges leaving the component. Pick any node not in the component and repeat. If you get into a situation when you have a few components that are all 2-colored, and there are no edges leaving any of them, and you encounter an edge that originates in a node in the component you are currently building and goes into a node in one of the previous components then you just merge the current component with the older one (and possibly need to flip the color of every node in one of the components -- flip it in the smaller component). After merging just continue. You can do the merge, because at the time of the merge you have scanned only one edge between the two components, so flipping the coloring of one of the components leaves you in a valid state.
The time complexity is still O(max(|N|,|E|)), and all you need is an extra field for every node indicating which component that node is in.
How do you find out whether an undirected graph is Biconnected or not using its depth first search traversal.
Is there any other way than traversing the whole graph to find disconnected pieces of the graph.
You calculate the low(v) for every vertex in linear time (i.e. during the execution of the DFS). And there exists a bridge (i.e. an edge whose removal will disconnect the graph ==> not biconnected) iff there's a non-root vertex whose low value is itself OR if the root has more than one child.
It's explained here on point 5.2 http://www.cse.ohio-state.edu/~lai/780/graph.pdf
I have no answer to this, but my gut feeling would suggest that you would have to do the depth first search traversal as the biconnected property of the graph is a property of the whole graph and not any subset of the graph.