I am reading the application of BFS algorithm. One of the application which i read is to check weather a give graph is bipartite graph or not.Now I want to know, is there any algorithm to convert a graph into bipartite set/graph.
For example we have give a set of edges as
E={ (4, 1),( 1 ,2), (2 ,3),( 7, 2),( 1 ,5),( 8 ,4), (5 ,8),( 8, 9)}
and set of vertices
V= { 1,2,3,4,5,6,7,8}
we have to create bipartite set/graph.
Expected output as :-
s1={1 ,4, 8, 1 ,7 ,3}
s2={2, 5, 6, 9}
The general BFS algorithm to check if a graph is bipartite is:
Start from a vertex v_0, and label it s1.
Mark all v_0's neighbours as s2, and queue them.
Mark all the neighbour's neigbours as s1, and queue them
If, at any point, you get to mark as s2 a vertex already marked as s1 or vice versa, the graph is not bipartite. If, instead, you end up with an empty queue, you are done, and you have your partition.
EDIT
If what you want to know, instead, is how you can build a bipartite graph from a general one, you should first add a metric to compare two different solutions : otherwise, removing all the edges and assigning randomly the vertices to two groups, will always generate a ( trivial ) bipartite graph from any given one.
The edge bipartization problem, that is, deleting the minimum number of edges to make a graph bipartite, is NP-hard. Here are slides of a talk about how to solve it as efficiently as possible.
Related
Consider the following directed graph. For a given n, the vertices of the graph correspond to the
integers 1 through n. There is a directed edge from vertex i to vertex j if i divides j.
Draw the graph for n = 12. Perform a DFS of the above graph with n = 12. Record the discovery
and finish times of each vertex according to your DFS and classify all the edges of the graph into tree, back, forward, and cross edges. You can pick any start vertex (vertices) and any order of visiting the vertices.
I do not see how it is possible to traverse this graph because of the included stipulations. It is not possible to get a back edge because a dividing a smaller number by a larger number does not produce an integer and will never be valid.
Say we go by this logic and create a directed graph with the given instructions. Vertex 1 is able to travel to vertex 2, because 2 / 1 is a whole number. However, it is impossible to get to vertex 3 as vertex 2 can only travel to vertex 4, 6, 8, or 10. Since you cannot divide by a bigger number it will never be possible to visit a lower vertex once taking one of these paths and therefore not possible to reach vertex 3.
Your assumption about the back tracks is correct. You cannot have back tracks because you don't have any circles. Consider the following example:
When we start at 2 we will find the edges 2->4, 4->8, 4->12, 2->6 and 2->10. The edges 2->8 and 2->12 are forward edges, they are like shortcuts to get forward much faster. The edge 6->12 is a cross edge because you are switching from one branch to another branch. And since we have no circles to somehow get back to a previous node, we don't have any backward edges.
Given an undirected graph, I want an algorithm (inO(|V|+|E|)) that will find me the heaviest edge in the graph that forms a cycle. For example, if my graph is as below, and I'll run DFS(A), then the heaviest edge in the graph will be BC.
(*) In this problem, I have at most 1 cycle.
I'm trying to write a modified DFS, that will return the desired heavy edge, but I'm having some trouble.
Because I have at most 1 cycle, I can save the edges in the cycle in an array, and find the maximum edge easily at the end of the run, but I think this answer seems a bit messy, and I'm sure there's a better recursive answer.
I think the easiest way to solve this is to use a union-find data structure (https://en.wikipedia.org/wiki/Disjoint-set_data_structure) in a manner similar to Kruskal's MST algorithm:
Put each vertex in its own set
Iterate through the edges in order of weight. For each edge, merge the sets of the adjacent vertices if they're not already in the same set.
Remember the last edge for which you found that its adjacent vertices were already in the same set. That's the one you're looking for.
This works because the last and heaviest edge that you visit in any cycle must already have its adjacent vertices connected by edges you visited earlier.
Use Tarjan's Strongly Connected Components algorithm.
Once you have split your graph into many strongly connected graphs assign a COMP_ID to each node which specifies the component ID to which this node belongs (This can be done with a small edit on the algorithm. Define a global integer value which starts at 1. Every time you pop nodes from the stack they all correspond to the same component, save the value of this variable to the COMP_ID of these nodes. When the pop loop ends increment the value of this integer by one).
Now, iterate over all the edges. You have 2 possibilities:
If this edge links two nodes from two different components, then this edge can't be the answer, since it can't possibly be a part of a cycle.
If this edge links two nodes from the same component, then this edge is a part of some cycle. All you have left to do now is to choose the maximum edge among all the edges of type 2.
The described approach runs in a total complexity of O(|V| + |E|) because every node and edge corresponds to at most one strongly connected component.
In the graph example you provided COMP_ID will be as follows:
COMP_ID[A] = 1
COMP_ID[B] = 2
COMP_ID[C] = 2
COMP_ID[D] = 2
Edge 10 connects COMP_ID 1 with COMP_ID 2, thus it can't be the answer. The answer is the maximum among edges {2, 5, 8} since they all connect COMP_ID 1 with it self, thus the answer is 8
How to go from an edge list or adjacency list representation of a planar graph to a face list?
For example, with this graph (which is not 0-indexed, oddly enough):
I'd want a list that looks something like this:
[
[1,2,8,7],
[1,2,4,3],
[1,3,5,7],
[2,4,6,8],
[5,6,7,8],
[3,4,6],
[3,5,6]
]
It wouldn't have to be in that format or order, but it should be some kind of list (or set) of all faces. The outer face is included.
For a graph with V vertices (E=O(V) because planar), the algorithm should generate this list in O(V).
You need to generate a planar embedding of the graph. One issue is that often a biconnected graph can generate multiple planar embeddings.
One planarity testing and embedding algorithm is given in the "Planarity Testing by Path Addition" PhD thesis and this solves the problem of generating all possible planar embeddings of a graph (in O(V+E) time and memory for a single embedding for a biconnected graph with V vertices and E edges, and in O(P(V+E)) time and O(V+E) memory to generate all possible unique planar embeddings, where P is the number of permutations of embeddings).
Chapter 5 details the algorithm needed to test a graph for planarity and then to generate a cyclic edge order for each vertex (and also how to iterate to the next permutation of the embedding).
Given a cyclic edge order, you can generate the faces of the graph by taking each edge and following the next clockwise (or anti-clockwise) edge in the cyclic edge ordering as you come to each successive vertex.
The short answer is : you have to actually layout the graph! More exactly, you have to find an embedding of the graph in the plane - assuming that there is one without edge crossings.
So, your embedding above is :
1: [2, 7, 3]
2: [1, 4, 8]
3: [1, 5, 6, 4]
...
which is each vertex with an ordering on its neighbour set. You have to specify if that ordering is clockwise or anti-clockwise, but otherwise that should be all.
Once you have the embedding, it is possible to recover the faces using a combinatorial map. This looks trickier than it really is, although it does involve darts (or flags).
First, break each edge into flags (vertex + half-edge) and make a permutation (sigma in the wiki description) that stores the map. For example, we could label the flags in the same order as the map - then 1: [2, 7, 3] becomes {1->2 : 1, 1->7 : 2, 1->3 : 3} and so on.
For example, a cube (note : removed the middle edge!):
Then calculate alpha (the involution permutation) which just maps flags to the other flag across the edge. Finally, phi is the product of these two permutations, and the cycles of phi gives you the faces.
So, from the phi in the image, we have (1, 6, 24, 19) which is the outer face (note that these are darts, so we consider the vertex it starts from).
As #gilleain mentioned in his answer, you have to actually layout the graph, as there could be multiple layouts if you just give the topology. Here I'll give some algorithmic analysis and then a straightforward solution.
Lemma 1: An edge is involved in at least one face, and at most two
faces.
Proof: We're drawing in 2D space so a line splits a plane into two halves.
This means that we can attach a "capacity" to each of the edges, initialized to 2. When we find an face involving an edge, we subtract 1 from it.
As a face is a loop in the planar graph, the problem turns to find loops given the aforementioned constraint.
Lemma 2: If we examine the difference between two valid solutions, they differ in edges that have complementary capacities (1 vs. 2 and 2 vs. 1).
Proof: See the figure.
As a consequence, when you drain the capacity for an edge when finding a solution, you automatically exclude the ambiguity that leads to another solution.
So the straightforward solution is to conduct DFS in the graph to find loops. When you find one, subtract the capacities of the involved edges. When the capacity reaches 0, consider the edge removed when DFS further. Note, when a loop is found, we must check if all the edges within have capacity 1. If so, then this loop must be skipped, as including this loop into our result leads to repeated counting.
def DFS-Tarjan(v, capacities, stack)
for e in N(v):
if capacity[e] != 0:
if stack.contains[e.target] AND NOT all of them have capacity 1:
output-loop(stack, e.target)
for e2 in stack:
capacity[e2] -= 1
else:
stack.push(e.target)
DFS-Tarjan(v, capacities, stack)
stack.pop(e.target)
else:
pass # capacity drained
def find-faces(g):
initialize capacities of g.E to [2...2]
for v in unvisited(g.V):
DFS-Tarjan(v, capacities, [])
Multiple solutions can be found if you alter the order for DFS. For a single solution, the algorithm is O(V) as each edge is consumed no more than twice.
I stuck in one challenging question, I read on my notes.
an Undirected, Weighted and Connected Graph G, (without negative weight and all weights are distinct) is given, we know in this graph the shortest path between any two vertexes is on Minimum Spanning Tree (MST). (for any pair of vertices and for any shortest path between them, it lies on MST). Which of The following Is True?
1) Graph G is a Tree.
2) weight of each {u,v} edge, at least is equal (same) to heaviest edge in shortest path from u to v.
3) shortest path between any two vertex u, v is unique.
4) suppose start from vertex s, Prime (for calculating MST) and Dijkstra (for calculating shortest path), process and add the
vertexes into their Trees, with the same order. (two algorithm works with same order in processing and adding node)
How can verify me these options? This is a challenging question.
No. For example: V = {1, 2, 3}, E = {(1, 2, 1), (2, 3, 2), (1, 3, 4)}(each edge is encoded as a tuple (one vertex, another vertex, weight)). It is not a tree, but all shortest path are on the minimum spanning tree.
Yes. If the weight of this edge is less than the weight of the heaviest edge which is in the shortest path, this edge is shorter than the shortest path(because there are no edges with negative weight). Thus, the shortest path is not the shortest. It is a contradiction.
No*. Let's assume that we have a graph with two vertices {1, 2} and one edge between them with zero weight. There are infinitely many shortest paths between the first and the second vertex([1, 2], [1, 2, 1, 2], ...)
*However, there is a unique simple shortest path between any two vertices because there is only one simple path between any two vertices in a tree, any path which does not fully lie in a minimum spanning tree is longer due to the problem statement and there is only one minimum spanning tree in a graph with distinct edges weights.
No. Consider this tree: V = {1, 2, 3, 4}, E = {(1, 2, 3), (2, 3, 2), (1, 4, 4)}. Let's assume that the start vertex is 1. Prim's algorithm will take the first vertex, than the second one, than the third one and only after this the fourth. But Dijkstra's algorithm will take the fourth vertex before the third one. It happens because the third vertex is located closer to the tree after processing the first two vertices, but it the total distance to it from the start node is larger.
I do not want to give the complete answer, but here is how you approach it:
Can you add edge[s] to the tree such that it is not a tree anymore and still the tree contains all the shortest paths?
What happens if there is an edge that is shorter than the heaviest edge?
it is confusing because the problem says "the shortest path between any two vertexes is on MST", but doesn't address the fact that there might be multiple shortest paths. So you can probably assume that "at least one shortest path lies on the tree". In which case just connect two vertices with an edge whose weight equals to cost through the MST, and you get the answer.
Again, you should start with what happens if the vertices are not added in the same order
I am reading Introduction to Algorithms. In 22.5 Strongly Connected Component, the algorithm STRONGLY-CONNECTED-COMPONENT(G) is defined as:
Call DFS(G) to compute finishing times u.f for each vertex u
Compute G transpose
Call DFS(G transpose), but in the main loop of DFS, consider the vertices in order of decreasing u.f(as computed in line 1)
Output the vertices of each tree in the depth-first forest formed in line 3 as a separate strongly connected component
If I change the alogrithm to just using G, without calculating G transpose. Also consider the vertices in order of Increasing u.f(Reverse order of topological sort):
Call DFS(G) to compute finishing times u.f for each vertex u
Call DFS(G), but in the main loop of DFS, consider the vertices in order of increasing u.f(as computed in line 1)
Output the vertices of each tree in the depth-first forest formed in line 2
Why is this algorithm wrong?
Your question is actually exercise 22.5-3 in the book. A counter example to the correctness of your alternative algorithm is given here:
http://sites.math.rutgers.edu/~ajl213/CLRS/Ch22.pdf
Professor Bacon’s suggestion doesn’t work out. As an example, suppose that
our graph is on the three vertices {1, 2, 3} and consists of the edges (2, 1),(2, 3),(3, 2).
Then, we should end up with {2, 3} and {1} as our SCC’s. However, a possible
DFS starting at 2 could explore 3 before 1, this would mean that the finish
time of 3 is lower than of 1 and 2. This means that when we first perform the
DFS starting at 3. However, a DFS starting at 3 will be able to reach all other
vertices. This means that the algorithm would return that the entire graph is a
single SCC, even though this is clearly not the case since there is neither a path
from 1 to 2 of from 1 to 3.
The vertices in strongly connected component are, by definiton, connected to each other (by a path, not necessarily by direct edge). if you make first DFS call on vertex X, you find out "which vertices is X connected to" (X -> N). To make sure that all those vertices are connected to X (N -> X) and therefore validate strong connectivity you need to traverse the edges in reversed directions. The easiest way to do such is by transposing the graph.
If you look for proof of the algorithm, i am sure you will find some. It may not be the easiest to understand but check this source for example:
Correctness of the algorithm for finding strongly connected components