Finding Connected Components - algorithm

I want to find connected components of a Directed Acyclic Graph using a set of nodes. What would be the most efficient way to solve this problem?
Connected Component: If one of the nodes is a predecessor or
successors of another node, they are in the same connected component.
For example, let's say I have the following graph and vector = [2,4,5,6,3]. For this vector, there are two connected component as below.
C1 = [2,4,5,6]
C2 = [3]
My solution:
Sort the nodes using their depth value
Pick a node
Check the other nodes if they are successors or not. If so, keep
looking. If not, stop and go to step 2.
What do you think?

I hope I understand your definition of connected component...If that's the case
I agree with #anonymous, you can simply make the graph undirected and find the connected components using simple DFS...
I do not quite understand your original thought, at least I think the implementation will be a bit complicated, say for edges {1-->2, 2-->4, 3-->4},
Node #1 and #3 will be sorted at the beginning of the list, and how can you know {1,2,3,4} is a single connected component?
Anyhow, the complexity is the same with the simple DFS method, at best, which is O(V)
(If anyone think this answer is correct, please give all credits to #anonymous!)

The way to find connected component is something like following :
while(anymore_root_vertex_tostartfrom){
vertex v=pick_a_vertex;
remove vertex from root_vertex_list;
initialize connected_comp_list_of_vertices;
do a breadth_first traversal from this vertex
keep adding the vertex you encounter in bfs to connected_comp_list_of_vertices
of that root
}
I would suggest reading some more about Graph processing. Finding connected component, BFS, DFS traversal have fairly standard techniques. An excellent book on this subject is Skiena's Algoritham Design Manual

Related

Pairs of Vertices Unreachable from Each Other in a Directed Graph

I am requested to design an algorithm to determine whether there exists any pair of vertices unreachable from each other in a directed graph. The algorithm must run in O(|V| + |E|) time
Meaning: vertex i cannot reach vertex j, and vertex j cannot reach vertex i.
I have read about the method for finding strongly connected components, I wonder whether or not I can start from there and devise an algorithm usable under the current circumstance?
If you can find all strongly connected components in the linear O(V + E) time requested then you are done. This may seem a bit overkill but it solves the problem. To find all strongly connected components, assuming your graph is represented as an adjacency list, perhaps the simplest O(V + E) linear time algorithm is Kosaraju's, see e.g. http://en.wikipedia.org/wiki/Kosaraju%27s_algorithm
Once you find all strongly connected components, then it is fairly simple to test whether there is a pair of strongly connected components that is not connected by any path, by considering the condensed graph where nodes are strongly connected components and an edge exists if there is an edge between any two nodes chosen from the two connected components.
Here are a few hints to help you get started:
Try solving this problem first when the graph you're given is a DAG. What does the structure of the DAG have to be in order for any pair of nodes to be at least weakly connected?
If you compute the strongly-connected components of a graph, those SCCs themselves form a DAG. Could you use this observation, in conjunction with your algorithm for part (1), to form an algorithm that works on arbitrary graphs?
Hope this helps!
If you are able to find the strongly connected components then you conversely know the vertices that are not connected as well.
The wiki: http://en.wikipedia.org/wiki/Kosaraju%27s_algorithm is pretty instructive. I have implemented the algorithm and it is available here. Runs in O (v + E ). We are assuming that the graph is backed as an adjacency list.
Link for Kosaraju Implementation in Java
Try it out, hopefully you would find no bugs :-)

Creating a graph and finding strongly connected components in a single pass (not just Tarjan!)

I have a particular problem where each vertex of a directed graph has exactly four outward-pointing paths (which can point back to the same vertex).
At the beginning, I have only the starting vertex and I use DFS to discover/enumerate all the vertices and edges.
I can then use something like Tarjan's algo to break the graph into strongly connected components.
My question is, is there a more efficient way to doing this than discovering the graph and then applying an algorithm. For example, is there a way of combining the two parts to make them more efficient?
To avoid having to "discover" the graph at the outset, the key property that Tarjan's algorithm would need is that, at any point in its execution, it should only depend on the subgraph it has explored so far, and it should only ever extend this explored region by enumerating the neighbours of some already-visited vertex. (If, for example, it required knowing the total number of nodes or edges in the graph at the outset, then you would be sunk.) From looking at the Wikipedia page it seems that the algorithm does indeed have this property, so no, you don't need to perform a separate discovery phase at the start -- you can discover each vertex "lazily" at the lines for each (v, w) in E do (enumerate all neighbours of v just as you currently do in your discovery DFS) and for each v in V do (just pick v to be any vertex you have already discovered as a w in the previous step, but which you haven't yet visited yet with a call to strongconnect(v)).
That said, since your initial DFS discovery phase only takes linear time anyway, I'd be surprised if eliminating it sped things up much. If your graph is so large that it doesn't fit in cache, it could halve the total time, though.

Vertices in directed graph such that there exists a path to every another vertex from this one

How can I find all vertices in a directed graph such that every another vertex is reachable from this one? Now I can "invent" only O(|V|^3) algo -- a DFS/BFS from every vertex, but I'm sure, there exists a faster way to solve this.
Thank you!
Run a strongly connected components algorithm to collapse the graph into a directed acyclic graph of its strongly connected components. There must be at least one strongly connected component with no incoming edges. If there is exactly one, the nodes in that component are the ones you're looking for. If there are multiple strongly connected components with no incoming edges, there is no node from which all other nodes are reachable.
EDIT: See comments below!
Sometimes it's all about the terminology. Here the magic word is reachability (see Wikipedia). Unfortunately, I don't think you'll like the results.
If not all the answers are needed, running BFS/DFS is actually recommended.
Otherwise, use the Floyd-Warshall algorithm. Still runs in O(|V|3).
Certain optimized algorithms exist for special cases - see Wikipedia for more detail.
So that's probably not what you wanted to hear.

How to detect if breaking an edge will make a graph disjoint?

I have a graph that starts off with a single, root node. Nodes are added one by one to the graph. At node creation time, they have to be linked either to the root node, or to another node, by a single edge. Edges can also be created and deleted (one by one, between any two nodes). Nodes can be deleted one at a time. Node and edge creation, deletion operations can happen in any arbitrary order.
OK, so here's my question: When an edge is deleted, is it possible do determine, in constant time (i.e. with an O(1) algorithm), if doing this will divide the graph into two disjoint subgraphs? If it will, then which side of the edge will the root node belong?
I'm willing to maintain, within reasonable limits, any additional data structure that can facilitate the derivation of this information.
Maybe it is not possible to do it in O(1), if so any pointers to literature will be appreciated.
Edit: The graph is a directed graph.
Edit 2: OK, maybe I can restrict the case to deletion of edges from the root node. [Edit 3: not, actually] Also, no edge lands into the root node.
To speed things up a little over the obvious O(|V|+|E|) solution, you could keep a spanning tree which is fairly easy to update as the graph is changed.
If an edge not in the spanning tree is deleted, then the graph isn't disconnected and do nothing. If an edge in the spanning tree is deleted, then you must try to find a new path between those two vertices (if you find one, use it to update the spanning tree, otherwise the graph is disconnected).
So, best case O(1), worst-case O(|V|+|E|), but fairly simple to implement anyway.
Is this a directed graph? The below assumes undirected.
What you are looking for is whether the given edge is a Bridge in the graph. I believe this can be found using a traversal looking for cycles containing that edge and would be O(|V| + |E|).
O(1) is too much to ask.
You might find that looking to maintain 2-edge connected components in dynamic graphs could be useful to you.
Eppstein et al have a paper on this: http://www.ics.uci.edu/~eppstein/pubs/EppGalIta-TR-93-20.pdf
which can maintain 2-edge connected components, in a graph of n nodes where edge insertions and deletions are allowed. It has O(sqrt(n)) time per update and O(log n) time per query.
So any time you delete, you can query in O(logn) to determine if the number of 2-edge connected components has changed. I suppose it can also tell you which component a specific node is in.
This paper is more general and applies to other graph problems, not only 2 edge connected components.
I suggest you look for bridges and dynamic 2-edge connectivity to get you started.
Hope that helps.
as said by Moron just before, you are actually looking for a Bridge in your graph.
Now a Bridge is an edge that has the described attribute and also originates and ends up in Cut Vertexes. Cut vertex is exactly what a Bridge is, but in a vertex (node) edition.
So the only way (though quite bending the initial data structure hypothesis) I can think of, to get a O(1) complexity for this, is if you first check every node in your graph if it is a Cut Vertex and then simply in constant time checking if the edge you want to delete is a attached to one of those two.
Finding if a node in a graph is a Cut Vertex takes O(m+n) where m = # edges and n= # nodes.
Cheers

How do I test whether a tree has a perfect matching in linear time?

Give a linear-time algorithm to test whether a tree has a perfect matching,
that is, a set of edges that touches each vertext of the tree exactly once.
This is from Algorithms by S. Dasgupta, and I just can't seem to nail this problem down. I know I need to use a greedy approach in some manner, but I just can't figure this out. Help?
Pseudocode is fine; once I have the idea, I can implement in any language trivially.
The algorithm has to be linear in anything. O( V + E ) is fine.
I think I have the solution. Since we know the graph is a tree, we know of the existance of leaf nodes, nodes with one edge and no children. In order for this node to be included in the perfect matching, that edge MUST exist in the final solution.
Ergo, we can find all edges connecting to a leaf node, add to the solution, and remove the touched edges from the graph. If, at the end of this process, we are left any remaining nodes untounched, there exists no perfect matching.
In the case of a "graph",
The first step of the problem should be to find the connected components.
Since every edge in the final answer connect two vertices, they belong to at most one of the connected components.
Then, the perfect matching could be found for each connected component.
Linear in what? Linear in the number of edges, keep the edges as an ordered incidence list, ie, every edge (vi, vj) in some total order. Then you can compare the two lists in O(n) of the edges.
The working algorithm would be something as follows:
For each leaf in the tree:
add edge from leaf to its parent to the solution
delete edge from leaf to its parent
delete all edges from the parent to any other vertices
delete leaf and parent from the tree
If the tree is empty then the answer is yes. Otherwise, there's no perfect matching.
I think that it's a simplified problem of finding a Hamiltonian path in a graph:
http://en.wikipedia.org/wiki/Hamiltonian_path
http://en.wikipedia.org/wiki/Hamiltonian_path_problem
I think that there are many solutions on the internet to this problem, but generally finding Hamilton cycle is a NP problem.

Resources