Use O(n^2) time to fix a mistake in bipartite matching - algorithm

This is a problem from Algorithm Design book.
Given a bipartite graph with vertices G=(V,E) where V=(A,B) such that |A|=|B|=n.
We manage to perfectly match n-2 nodes in A to n-2 nodes in B. However, for the remaining two nodes in A we map them both to a certain node in B (not one of the n-2 nodes in B that are already matched to.)
Given the information from the "matching" above, how to use O(n^2) time to decide whether a perfect matching between A and B actually exists? A hint is fine. Thank you.

Let's have u and v be the two nodes in A that match to the same node x in B. Pick one of those two nodes - call it u - and remove the edge to x from the matching. You are now left with a graph where you have a matching between n - 1 of the nodes from A and n - 1 of the nodes from B. The question now is whether you can extend this matching to make it even bigger.
There's a really nice way to do this using Berge's theorem, which says that a matching in a graph is maximum if and only if there is no alternating path between two unmatched nodes. (An alternating path is one that alternates between using edges not included in the matching and edges included in the matching). You can find a path like this by starting from the node u and trying to find a path to x by doing a modified binary search, where when you go from A to B you only follow unmatched edges and when you go from B back to A you only follow matched edges. If an alternating path exists from u to x, then you'll be sure to find it this way, and if no such path exists, then you can be certain of that as well.
If you do find an alternating path from u to x, you can "flip" it to increase the size of the matching by one. Specifically, take all the edges in the path that aren't in the matching and add them in, and take all the edges that were in the matching and delete them. The resulting is still a valid matching that has one more edge in it than what you started with (if you don't see why this is, play around with some examples and see what you find, or look at the proof of Berge's theorem).
Overall, this approach will require time O(m + n), where m is the number of edges in the graph and n is the number of nodes. The number of edges m is at most O(n2) in a bipartite graph, so this matches your time bound (and, in fact, is actually a bit tighter!)

Transform this problem to the max flow min cut problem by adding a source s which is connected to A by unit capacity edges and a sink t to which B is connected by unit capacity edges.
As templatetypedef said in their answer, we already have a flow of size n-1 on this network.
The problem is now to determine whether the size of the flow can be increased to n. This can be achieved by running one round of Edmonds-Karp heuristic which takes O(E)=O(n^2) time (i.e find the shortest path in the residual graph of the flow of size n-1 above and look for the bottleneck edge.)

Related

What algorithm should I use to get all possible paths in a directed weighted graph, with positive weights?

I have a directed weighted graph, with positive weights, which looks something like this :-
What I am trying to do is:-
Find all possible paths between two nodes.
Arrange the paths in ascending order, based on their path length (as given by the edge weights), say top 5 atleast.
Use an optimal way to do so, so that even in cases of larger number of nodes, the program won't take much time computing.
E.g.:- Say my initial node is d, and final node is c.
So the output should be something like
d to c = 11
d to e to c = 17
d to b to c = 25
d to b to a to c = 31
d to b to a to f to c = 38
How can I achieve this?
The best approach would be to take the Dijkstra’s shortest path algorithm, we can get a shortest path in O(E + VLogV) time.
Take this basic approach to help you find the shortest path possible:
Look at all nodes directly adjacent to the starting node. The values carried by the edges connecting the start and these adjacent nodes are the shortest distances to each respective node.
Record these distances on the node - overwriting infinity - and also cross off the nodes, meaning that their shortest path has been found.
Select one of the nodes which has had its shortest path calculated, we’ll call this our pivot. Look at the nodes adjacent to it (we’ll call these our destination nodes) and the distances separating them.
For every ending (destination node):
If the value in the pivot plus the edge value connecting it totals less than the destination node’s value, then update its value, as a new shorter path has been found.
If all routes to this destination node have been explored, it can be crossed off.
Repeat step 2 until all nodes have been crossed off. We now have a graph where the values held in any node will be the shortest distance to it from the start node.
Find all possible paths between two nodes
You could use bruteforce here, but it is possible, that you get a lot of paths, and it will really take years for bigger graphs (>100 nodes, depending on a lot of facotrs).
Arrange the paths in ascending order, based on their path length (as given by the edge weights), say top 5 atleast.
Simply sort them, and take the 5 first. (You could use a combination of a list of edges and an integer/double for the length of the path).
Use an optimal way to do so, so that even in cases of larger number of nodes, the program won't take much time computing.
Even finding all possible paths between two nodes is NP-Hard (Source, it's for undirected graphs, but is still valid). You will have to use heuristics.
What do you mean with a larger number of nodes? Do you mean 100 or 100 million? It depends on your context.

Algorithm: Minimal path alternating colors

Let G be a directed weighted graph with nodes colored black or white, and all weights non-negative. No other information is specified--no start or terminal vertex.
I need to find a path (not necessarily simple) of minimal weight which alternates colors at least n times. My first thought is to run Kosaraju's algorithm to get the component graph, then find a minimal path between the components. Then you could select nodes with in-degree equal to zero since those will have at least as many color alternations as paths which start at components with in-degree positive. However, that also means that you may have an unnecessarily long path.
I've thought about maybe trying to modify the graph somehow, by perhaps making copies of the graph that black-to-white edges or white-to-black edges point into, or copying or deleting edges, but nothing that I'm brain-storming seems to work.
The comments mention using Dijkstra's algorithm, and in fact there is a way to make this work. If we create an new "root" vertex in the graph, and connect every other vertex to it with a directed edge, we can run a modified Dijkstra's algorithm from the root outwards, terminating when a given path's inversions exceeds n. It is important to note that we must allow revisiting each vertex in the implementation, so the key of each vertex in our priority queue will not be merely node_id, but a tuple (node_id, inversion_count), representing that vertex on its ith visit. In doing so, we implicitly make n copies of each vertex, one per potential visit. Visually, we are effectively making n copies of our graph, and translating the edges between each (black_vertex, white_vertex) pair to connect between the i and i+1th inversion graphs. We run the algorithm until we reach a path with n inversions. Alternatively, we can connect each vertex on the nth inversion graph to a "sink" vertex, and run any conventional path finding algorithm on this graph, unmodified. This will run in O(n(E + Vlog(nV))) time. You could optimize this quite heavily, and also consider using A* instead, with the smallest_inversion_weight * (n - inversion_count) as a heuristic.
Furthermore, another idea hit me regarding using knowledge of the inversion requirement to speedup the search, but I was unable to find a way to implement it without exceeding O(V^2) time. The idea is that you can use an addition-chain (like binary exponentiation) to decompose the shortest n-inversion path into two smaller paths, and rinse and repeat in a divide and conquer fashion. The issue is you would need to construct tables for the shortest i-inversion path from any two vertices, which would be O(V^2) entries per i, and O(V^2logn) overall. To construct each table, for every entry in the preceding table you'd need to append V other paths, so it'd be O(V^3logn) time overall. Maybe someone else will see a way to merge these two ideas into a O((logn)(E + Vlog(Vlogn))) time algorithm or something.

BFS? - find all paths from s to t that have at most a certain length

Given an undirected (connected) graph, I want to list all paths from s to t that use at most k edges.
A naive approach would, of course, just take a BFS and stop it after k steps from s (or a DFS where we cut off after k steps), reporting whatever paths end up in t.
I was wondering whether there was a more sophisticated way to do this?
I cannot see how you could use a BFS or DFS here. Since you need to enumerate all possible paths from s to t, then you cannot solve it without some recursive search. Moreover, generally the amount of paths would be exponential in k, so do not hope for any major asymptotic complexity improvements.
To my mind, only pruning can slightly help you.
Here are two ways of pruning worth mentioning:
The first one is the meet-in-the-middle approach.
Instead of searching for all vertices at distance <= k from vertex s, find two groups of vertices: at distance <= k/2 from s, and at distance <= k/2 from t. Just launch two searches (BFS or recursive) to get them. Finally, merge the results: for each common vertex v in these two sets, take all pairs of paths from s to v and paths from t to v (reversed), and output the joined path.
The exact approach described above would list some paths several times. In order to fix it, store paths of each particular length in a separate list. Then merge paths of each length separately.
Note that if you want to get only simple paths (i.e. no vertex repeated), then the MitM approach is not applicable.
The second way is to use distance estimates, similar to how A* search algorithm does it. Suppose that you have guaranteed lower bounds on distance from any vertex v to destination vertex t. Then you can drop any partial path from s to v if it surely cannot be continued to a sufficiently short full path from s to t.
This is not really a bfs that you need, because to get all the paths you must keep the adjacent vertices that you already visited.
With the following graph:
0->1
0->0
1->1
All the paths from 0 to 1 that contain 2 steps are [0,0,1],[0,1,1]
The naive solution is to keep a list of the nodes active at each step (with duplicates). To go from stem i to i+1, create a new list with all the adjacent vertices for each vertex (do not remove duplicates).

Destroy weighted edges in a bidirected graph

On my recent interview I was asked the following question:
There is a bidirectional graph G with no cycles. Each edge has some weight. Also there is a set of nodes K which should be disconnected from each other (by removing some edges). There is only one path between any two nodes in K set. The goal is to minimize total weight of removed edges and disconnect all nodes (from set K) from each other.
My approach was to run BFS for each node from K set and determine all paths between all pairs of nodes from K. So then I'll have set of paths (each path is a set of edges).
My next step is to apply dynamic programming approach to find minimum total weight of removed edges. And here I stuck. Could you please help me (just direct me) of how DP should be done.
Thanks.
This sounds like the Multiway Cut problem in trees, assuming a "bidirectional" graph is just like an undirected one. It can be solved in polynomial time by a straightforward dynamic programming. See Chopra and Rao: "On the multiway cut polyhedron", Networks 21(1):51–89, 1991. See also this question.
This problem can be solved using disjoint Sets. In this problem you need to make set of each vertex like forest. Then, join the vertices which belong to two different sets through the edges which are in the graph such that -
1) if one of the set contains a node which is mentioned in the k set of nodes, then the node becomes the representative element.
2) if both the sets contain the unwanted node (node present in the k set of nodes), then find the minimum weight edge in both the sets and compare them, then compare the minimum one of them with the edge to be joined and find the minimum. Then delete the edge which we found so that no path exists b/w them.
3) if none of the set contain the unwanted node, then join one set to the other set.
In this way you find the minimum total weight of the destroyed edges in a very good time complexity of the order of O(nlogn).
Your approach will also work but it will prove to be costly in terms of time complexity.
Here is the complete code - (GameAlgorithm.cpp)
https://github.com/KARTHEEKCIC/RoboAttack

finding whether a path of a specific length exists in an acyclic graph

In an acyclic graph, I am trying to find out whether or not a path of length L exists between two given nodes. My questions is, what is the best and the simplest Algorithm to use in this case.
Note that the graph has a maximum of 50 nodes and 100 edges.
I have tried to find all the paths using DFS and then to check if that path exists between the two nodes but I got the answer "Time Limit Exceeded" from the online judge.
I also used the Uniform Cost Search Algorithm but I also a got a negative response.
I need a more efficient way for solving such problem. Thank you.
I don't know if it will be faster then a DFS approach - but it will give a feasible solution:
Represent the graph as a matrix A, and calculate A^L - a path of length L between i and j exists if and only if A[i][j] != 0
Also, regarding DFS solution: You do not need to find all paths in the DFS - you should limit yourself to paths of length <= L, and by this trim some searches, once the length have exceeded the needed length. You could also escape the search once a path of length L is reaching the target.
Another possible optimization could be bi-directional search.
Find all vertices which have path of length L/2 from the source to
them.
Next, find all vertices which have paths of length L/2 from them
to the target (DFS on the reverse graph)
Then, check if there is a vertex that is common to both sets, if
there is - you got a path of length L from the source to the target.
Since the graph is acyclic you can order vertices topologicaly.
Let's name starting vertex A and finish vertex B.
Now the core algorithm starts:
For each vertex count all possible distances from A to this vertex. At start there is
one path from A to A with length zero.
Then take vertices in topological order.
When you pick vertex x: Look at each predecessor and update possible distances here.
This should run in O(N^3) time.
You can use a modified Dijkstra algorithm where instead of saving for every vertex the minimum distance to the origin, you save all the possible distances less or equal to the one desired.
I believe that you can use the following algorithm to find the longest path in a tree. This assumes that your graph is connected, if it is not you would need to rerun this on each connected component:
Pick an arbitrary node, A.
Do a BFS (or DFS) from A to find the node in the tree farthest from A, call this node B.
Do a BFS (or DFS) from B to find the node in the tree farthest from B, call this node C.
The path from B to C is the longest path in the tree (possibly tied for longest).
Obviously if this path is longer than L then you can shorten it to find a path of length L.

Resources