detecting mutual edges in a graph - algorithm

I have an adjacency list representation of a graph but it is not symmetric i.e,. if a node A has an edge to B, it is not true that B has an edge with A. I guess this will be a directional graph (digraph).
What is a good way to detect all the bidirectional paths from a node. I know I can use DFS to detect the paths from a node to another nodes of the graph. I guess what I am looking for is a bidirectional DFS where only the bidirectional edges are taken into account.
So one way to do that is to look at the neighbour for a node and figure out if this is a bidirectional relationship. However, for this I will need to go through all the immediate connections of this neighbouring node and see if the first node is also a connection and if yes, to continue with the recursion. I wonder if this is an efficient way to do this?

With a fairly standard "adjacency set" representation, where you use some sort of set data structure (hash- or tree-based) instead of lists to represent the edges coming out of a node, you can just query whether the reversed version of an edge exists in the graph. Building an adjacency set representation from an adjacency list representation is straightfoward.
Alternatively, you can build one set of all the edges in the graph and then filter edges out of the graph whose reversed version isn't in the set. This can be more convenient if you wouldn't have any further use for the adjacency set representation after using it in the other approach. If you want to keep memory usage down, you can remove edges from the set while building it if you find their reversed version in the graph, and then remove edges from the graph afterward if they're in the set instead of if their reversed version isn't.

Related

Dynamic Decremental Connectivity of Cubic Graph

Let's say I have a fully connected undirected graph (nodes and edges) that is constrained by the fact that all nodes represent coordinates in 3D space and nodes can only be adjacent in the graph if they represent adjacent cubes i.e. (1,0,8) could be adjacent to (0,0,8) or (2,0,8) or (1,0,9).
Now let's say I dynamically start deleting nodes from the graph. I'd like an algorithm that lets me know, at each delete, if the graph connectivity has been broken & if so what the connected components are. Is there a way to optimise the spatial nature of the graph to do so or am I doomed to using standard graph processing algorithms?
I'm thinking I'll need some sort of an algorithm that maintains dynamically the connectivity relationship of nodes in the graph as nodes are deleted from the graph. All I've managed to find so far is A*, jump point search and shortest path algorithms, and I also brushed upon an algorithm here: https://en.wikipedia.org/wiki/Dynamic_connectivity#Decremental_connectivity.
Note: my graph can definitely be cyclic.
OK, so after thinking about this, the best answer I can come up with still does not exploit the spatial constraints of the graph, but I believe it runs with an amortized cost of O(log(n). Here's a sketch of the idea:
First, we compute an arbitrary spanning tree of the graph, starting at any node and choosing arbitrary edges for the tree. Ideally we'd want to make this as balanced as possible i.e. minimize the depth.
Then, at each deletion, we update our spanning tree as follows:
If the edge deleted is not in the spanning tree, do nothing
Else, it's a parent-child relationship that's been removed, and we note the child node
For all children of this child node, we flag them temporarily i.e. we set some marker on each node marking it as part of this affected tree that's possibly broken from the main tree
Now we run this recursive algorithm, starting at the child node. Let's say the algorithm is currently processing node n:
If there is an edge from n in the graph to an unmarked node in the graph, update the spanning tree with this edge and return "true"
Else for each child of the node, we run the recursive algorithm and proceed as follows
If the algorithm returned false for any child, then the graph is broken i.e. disconnected
Else we can choose any node and point our node n at this node and return "true" ourselves
If we actually maintain two separate spanning trees, we can process edge deletions in the background and toggle between using one tree or the other, to improve the efficiency of this for use in a real-time program e.g. a game.

how to test for bipartite in directed graph

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.

Finding the list of common children (descendants) for any two nodes in a cyclic graph

I have a cyclic directed graph and I was wondering if there is any algorithm (preferably an optimum one) to make a list of common descendants between any two nodes? Something almost opposite of what Lowest Common Ancestor (LCA) does.
As user1990169 suggests, you can compute the set of vertices reachable from each of the starting vertices using DFS and then return the intersection.
If you're planning to do this repeatedly on the same graph, then it might be worthwhile first to compute and contract the strong components to supervertices representing a set of vertices. As a side effect, you can get a topological order on supervertices. This allows a data-parallel algorithm to compute reachability from multiple starting vertices at the same time. Initialize all vertex labels to {}. For each start vertex v, set the label to {v}. Now, sweep all vertices w in topological order, updating the label of w's out-neighbors x by setting it to the union of x's label and w's label. Use bitsets for a compact, efficient representation of the sets. The downside is that we cannot prune as with single reachability computations.
I would recommend using a DFS (depth first search).
For each input node
Create a collection to store reachable nodes
Perform a DFS to find reachable nodes
When a node is reached
If it's already stored stop searching that path // Prevent cycles
Else store it and continue
Find the intersection between all collections of nodes
Note: You could easily use BFS (breadth first search) instead with the same logic if you wanted.
When you implement this keep in mind there will be a few special cases you can look for to further optimize your search such as:
If an input node doesn't have any vertices then there are no common nodes
If one input node (A) reaches another input node (B), then A can reach everything B can. This means the algorithm wouldn't have to be ran on B.
etc.
Why not just reverse the direction of the edge and use LCA?

Check if a changing undirected graph has at least one circle

I have an undirected graph which initially has no edges. Now in every step an edge is added or deleted and one has to check whether the graph has at least one circle. Probably the easiest sufficient condition for that is
connected components + number of edges <= number of nodes.
As the "steps" I mentioned above are executed millions of times, this check has to be really fast. So I wonder what would be a quick way to check the condition depending on the fact that in each step only one edge changes.
Any suggestions?
If you are keen, you can try to implement a fully dynamic graph connectivity data structure like described in "Poly-logarithmic deterministic fully-dynamic graph algorithms I: connectivity and minimum spanning tree" by Jacob Holm, Kristian de Lichtenberg, Mikkel Thorup.
When adding an edge, you check whether the two endpoints are connected. If not, the number of connected components decreases by one. After deleting an edge, check if the two endpoints are stil connected. If not, the number of connected components increases by one. The amortized runtime of edge insertion and deletion would be O(log^2 n), but I can imagine the constant factor is quite high.
There are newer result with better bounds. There is also an experimental evaluation of some of the dynamic connectivity algorithms that considers implementation details as well. There is also a Javascript implementation. I have no idea how good it is.
I guess in practice you can have it much easier by maintaining a spanning forest. You get edge additions and non-tree edge deletions (almost) for free. For tree edge deletions you could just use "brute force" in the form of BFS or DFS to check whether the end points are still connected. Especially if the number of nodes is bounded, maybe that works well enough in practice, BFS and DFS are both O(n^2) for dense graphs and you can charge some of that work to the operations where you got lucky and didn't have a lot to do.
I suggest you label all the nodes. Use integers, that's easiest.
At any point, your graph will be divided into a number of disjoint subgraphs. Initially, each node is in its own subgraph.
Maintain the condition that each subgraph has a unique label, and all the nodes in the subgraph carry that label. Initially, just give each node a unique label. If your problem includes adding nodes, you might want to maintain a variable to hold the next available label.
If and only if a new edge would connect two nodes with identical labels, then the edge would create a cycle.
Whenever you add an edge, you will connect two previously disjoint subgraphs. You must relabel one of the subgraphs to match the other, which will require visiting all the nodes of one subgraph. This is the highest computatonal burden in this scheme.
If you don't mind allocating more space, you should also maintain a list of labels in use, associated with a count of the nodes carrying that label. This will allow you to choose the smaller subgraph when relabeling.
If you know which two nodes are being connected by the new edge, you could use some sort of path finding algorithm to detect an alternative path between the two nodes. In other words, if a path exists which connects the two nodes of your new edge before you add the new edge, adding the new edge will create a circle.
Your problem then reduces to finding the paths between two given nodes.

directed graphs with a given root node - match another directed graph for equality

There is a directed graph having a single designated node called root from which all other nodes are reachable. Each terminal node (no outgoing edges) takes an string value.
Intermediate nodes have one or more outgoing edges but no value associated with them. Edges connecting a node to its neighbor have a string label. The labels for edges emanating from a single node are unique. There could be possible cycles in the graph!
What is the best graph algorithm for checking if two such directed (possibly having cycles) graphs (as described above) are equal?
The graph isomorphism problem is one of the more intriguing problems in TCS. There is an entire page dedicated to it on the wiki.
In your particular case you have two rooted directed graph with a source and a sink.
You could start two BFS in parallel, and check for isomorphism level by level; i.e. levelize the graph and check whether the subset of nodes at each level are isomorphic across the two graphs.
Note that since you have a Directed, Rooted graph you should still be able to levelize it for the purpose of finding isomorphism. Do not enque nodes already visited during the BFS; i.e. levelize using the shortest path to the node from the root when determining the level to group in.
Within a set the comparison should be relatively easy. You have many properties to distinguish nodes at the same level (degree, labels) and should be able to create suitable signatures to sort them. Since you are looking for perfect isomorphism, you should get an exact match.

Resources