Complete Hungarian algorithm code with maximum matching in a Bipartite Graph

Source: Internet
Author: User

This article provides the idea and complete code for the Hungarian algorithm to find the maximum matching of a bipartite graph, and gives some comments on several small issues in algorithm learning. First, name the two sides of the Bipartite Graph as side A and side B. A key term for the Hungarian algorithm to calculate the maximum matching of a bipartite graph is the augmented path. The definition is: if P is a path in graph G that connects two unmatched vertices, and the edges that belong to M alternate with those that do not belong to M (that is, the edges that have been matched and to be matched) on P. P is an augmented path relative to M. Example: (1) If A vertex a1 on the a side is connected to A vertex b1 on the B side, and the edge a1b1 is not matched, in addition, Point a1 and b1 do not belong to the points of other matching edges, so a1b1 is an augmented path. In other words, for A bipartite graph, the edge connected to any A and B is an augmented path. (2) If edges a1b1, b1a2, and a2b2 are matched, a1b1 and a2b2 are not matched, and vertices a1 and b2 are not points of other matched edges, then these three edges form an augmented path. The following three conclusions can be drawn from the definition of augmented path: 1. The path length of P must be an odd number, and the first side and the last side do not belong to M. 2. P can get a larger matching m' after the reverse operation '. 3. M is the maximum matching of G if and only if there is no augmented path relative to M. Algorithm contour: (1) leave M (matching) blank (2) Find an augmented path P and obtain a larger matching m' by Reverse operations instead of M (3) repeat (2) until the augmented path is not found. If you have not learned this algorithm, you should be able to understand it here. Many articles have mentioned that finding the augmented path is not as follows, and the complete code is difficult to find. The following question comes: (3) how to repeat (2? Further refinement should be like this: in the initial stage, the maximum matching is null for each vertex I do on the side of the Bipartite Graph A. Find the augmented path from vertex I, then it is reversed (that is, the total number of matches is increased ). I haven't done any proof of the correctness of this algorithm. Let's talk about it first. When designing an algorithm, we generally don't want to prove its correctness. The greedy algorithm chapter in the general algorithm book involves the theory of proof of correctness (quasi-array), but little attention is paid to it. If you encounter this problem, you will know the importance of the correctness proof. Otherwise, you will always feel a little uneasy. First, let's take A look: we can find the augmented path from each vertex on the side so that the maximum matching plus one can be found. Then the maximum matching edge number is the same as the number of side A points, that is, vertices on the side are used, which is naturally the largest match. This is not complete yet. At most it will be 1/2. It is not very simple to find the augmented path for every time in a loop. Think of a famous Turing Award Winner's formula: "program = Algorithm + Data Structure ". I have never read a thesis that published this remark. I used to have an uncertain feeling about this sentence, or I need more evidence. Later, when I was writing an algorithm program, I realized that this sentence means that if I only understood the algorithm outline in general, it would be far behind, only by implementing this algorithm in a suitable data structure can we really understand it, because there is sometimes a big gap between understanding the algorithm framework and implementing it. This is just an obvious aspect. Further Algorithm Refinement: the bipartite graph is divided into two sides: A and B. This method can be seen as A deep traversal of side A. The processing methods for vertices on side A and side B are different. Copy the code to perform the following operations on each vertex on the side of the Bipartite Graph A (the side with fewer vertices can be considered as the side with A fewer vertices): 1. Set A [I] to the current vertex. 2. perform the following operations in turn using the points on side A and side B. (1) vertices A [I] On Side A: an unmatched edge is found. If the vertices on side B of an edge do not belong to another edge in the match, in this case, the augmented path is found (in the initial case, the maximum matching of an edge directly connected is the case), and the maximum matching is modified. If the B-side vertex of an edge belongs to another edge in the matching process, and the B-side vertex is set to B [j], it enters (2 ). If you cannot do this, you need to trace back. If the path is traced back to the starting point, it indicates that finding the augmented path from the starting point A [I] failed. Note: whether the augmented path can be found is determined by the vertices on the side (seeking and backtracking). The operations on vertices on the B side are very simple. (2) For vertices B on side B [j], the matching edge needs to be used because it is an augmented path, therefore, find the point A [k] corresponding to the matching edge of B [j] On Side A, and set A [k] to the current vertex to continue with step (1 ). In this process, the copy Code uses A queue record to find the vertices passing through the augmented path in A and B, so that you can trace back and find the augmented path and modify the maximum matching value. When designing algorithms, the role of pseudocode is embodied. The following is the complete implementation code based on the pseudo code: copy the Code # include <iostream> # include <deque> using namespace std; const int COUNTA = 6, COUNTB = 7; // Number of vertices on both sides of Bipartite Graph A and B int connection [COUNTA] [COUNTB] = {0}; // store the connections (edges) between vertices on both sides of A and B) int match [COUNTA] [COUNTB] = {0}; // match the points on both sides of A and B in struct elem {int element; int currentpartner ;}; deque <elem> que; void init () {connection [0] [0] = 1; connection [0] [1] = 1; connection [0] [3] = 1; connection [1] [1] = 1; connection [1] [4] = 1; connection [2] [0] = 1; connection [2] [3] = 1; connection [2] [6] = 1; connection [3] [2] = 1; connection [3] [3] = 1; connection [3] [5] = 1; connection [4] [3] = 1; connection [5] [3] = 1;} bool bPointInMatch (int point) // determines whether a point in B is matched {for (int I = 0; I <COUNTA; I ++) {if (match [I] [point] = 1) {return true ;}} return false ;} int bFindMatchPoint (int point) // query the point {for (int I = 0; I <COUNTA; I ++) {if (ma Tch [I] [point] = 1) {return I;} return-1;} void maxMatch () {elem queElem; for (int I = 0; I <COUNTA; I ++) {bool findAugmentPathA = false; int counter = 0; queElem. element = I; queElem. currentpartner =-1; que. push_back (queElem); // start point while (findAugmentPathA = false & counter> = 0) {if (! FindAugmentPathA) {int aPoint; bool findAugmentPathB = false; for (int j = que [counter]. currentpartner + 1; j <COUNTB; j ++) {if (connection [que [counter]. element] [j] = 1 & match [que [counter]. element] [j] = 0 &&! BPointInMatch (j) // find the augmented path {que [counter]. currentpartner ++; findAugmentPathA = true; // B inbound counter ++; queElem. element = j; queElem. currentpartner =-1; que. push_back (queElem); break;} else if (connection [que [counter]. element] [j] = 1 & match [que [counter]. element] [j] = 0 & bPointInMatch (j) {que [counter]. currentpartner ++; findAugmentPathB = true; counter ++; // B inbound stack queElem. element = j; queElem. curren Tpartner =-1; que. push_back (queElem); // It is found by B that the next A is merged into Stack aPoint = bFindMatchPoint (j); counter ++; queElem. element = aPoint; queElem. currentpartner =-1; que. push_back (queElem); break;} else {// TODO: Can I put the following if here?} If (! FindAugmentPathB) {counter = counter-2 ;}}// modify the maximum matching if (findAugmentPathA = true) {bool direction = false; for (int I = 0; I <que. size ()-1; I ++) {if (direction = false) {direction = true; match [que [I]. element] [que [I + 1]. element] = 1;} else {direction = false; match [que [I + 1]. element] [que [I]. element] = 0 ;}}while (que. size ()> 0) // clear the queue {que. pop_front () ;}/// maximum output matching for (int I = 0; I <COUNTA; I ++) {for (int j = 0; j <COUNTB; j ++) {if (match [I] [j] = 1) {cout <"(" <I <"," <j <") "<endl; break ;}}} int main () {init (); maxMatch (); return 0 ;}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.