The maximum weighted bipartite match problem is to give each edge of the Bipartite Graph A weight value, and select several non-intersecting edges to obtain the maximum total weight. To solve this problem, you can use the KM algorithm. To understand the KM algorithm, you must first understand the concept of "feasible top mark. A feasible top mark refers to a value of LX [I] Or ly [J] for each vertex on both sides of a bipartite graph. ensure that Lx [I] + ly [J]-W [I] [J]> = 0 is available for each edge W [I] [J. If a perfect match exists in all the export subgraphs that contain edges that meet the requirements of LX [I] + ly [J] = W [I] [J, therefore, this perfect match must be the maximum weight match in the source image. The reason is simple: the sum of the matched weights is exactly equal to the sum of all top-level values. Due to the inequality above, the sum of the weights of any other matching scheme is not greater than the sum of all top-level values.
However, the problem is that the current top-level export subgraph does not necessarily have a perfect match. In this case, you can adjust the logo in some way. The adjustment method is as follows: Based on the last unsuccessful search for the staggered DFS, obtain the edge (I, j) that is not accessed by J when I is accessed) the minimum value of LX [I] + ly [J]-W [I] [J] D. Reduce the top mark of all left endpoints in the staggered tree by D and the top mark of the right endpoint by D. After such adjustments: the edges in the original export subgraph have changed the top labels on both sides, and the equal signs of the inequality are still valid and are still in the export subgraph. The edges in the original export subgraph are not, the top mark of its left endpoint is reduced, the top mark of the right endpoint is not changed, and due to the definition of D, the inequality is still true, so it may enter the export subgraph.
Specify a feasible top mark at the beginning, for example, LX [I] = max {W [I] [J] | j is the right vertex}, and Ly [I] = 0. Then, execute the find process similar to the Hungary algorithm for each vertex. If a find operation fails, perform the above adjustments according to the points accessed by the find operation. In this way, we can gradually find the perfect match.
It is worth noting that it takes O (N ^ 2) Time to calculate d according to the definition of D above, because D needs to be calculated O (N ^ 2) times, this becomes the bottleneck of the algorithm. It can be optimized as follows: set slack [J] to the minimum value of LX [I] + ly [J]-W [I] [J] for all the edges of vertex J on the right, in the find process, if an edge is not in the export subgraph, it is used to update the corresponding slack value. Then find the minimum value in slack by using the O (n) time.
If we want to find the least weight match, we only need to reverse the inequality. The algorithm needs to make a change: the initial value of LX is the minimum value of all critical edges, and the T inverse number in find.
Max Weight Matching
/* HDU 2255 makes a fortune: There are n villagers and N houses. Each village name has a quote for each house, the maximum right matching between the quotation and the maximum arrangement is the optimal match. Here we have an explanation of the KM algorithm. h> # include <string. h> # define n 305int map [N] [N], Match [N], LX [N], Ly [N], slack [N], visx [N], visy [N]; int N; int hungray (int I) // The Hungary algorithm {Int J; visx [I] = 1; for (j = 1; j <= N; ++ J) // {If (visy [J]) continue; If (LX [I] + ly [J] = map [I] [J]) // If J is the same as the normal Hungary algorithm in an equal subgraph {visy [J] = 1; if (Match [J] =-1 | hungray (Match [J]) {match [J] = I; return 1 ;}} else if (Slack [J]> (LX [I] + ly [J]-map [I] [J]) // slack [J] = Lx [I] + ly [J]-map [I] [J];} return 0;} int km () {memset (match,-1, sizeof (MATCH); int I, j, D; memset (LX, 0, sizeof (LX); memset (ly, 0, sizeof (ly); for (I = 1; I <= N; I ++) // lx obtains the maximum edge connected to I. Right for (j = 1; j <= N; ++ J) if (Map [I] [J]> lx [I]) lx [I] = map [I] [J]; for (I = 1; I <= N; ++ I) // match each vertex {for (j = 1; j <= N; j ++) // For each vertex, you need to update lx and ly until you find the small difference value in the staggered slack storage. Therefore, initialize each vertex to the maximum slack [J] = 0x7fffffff; while (1) // jump out of {memset (visx, 0, sizeof (visx) when finding the staggered path; memset (visy, 0, sizeof (visy )); // initialize the access flag if (hungray (I) break; D = 0x7fffffff; // find the minimum change volume for (j = 1; j <= N; ++ J) if (! Visy [J] & slack [J] <D) d = slack [J]; for (j = 1; j <= N; ++ J) // Change {If (visx [J]) lx [J]-= D; If (visy [J]) ly [J] + = D; else slack [J]-= D; // For J that enters an equal subgraph through this update, this is meaningless. // For J instances that have not yet entered an equal subgraph, the connected I is-D, so that difference will decrease d, so here we modify slack }}d = 0; for (I = 1; I <= N; I ++) // The right of all edges indicates that the vertex D + = Lx [I], D + = ly [I]; return D ;}int main () {int I, j; while (scanf ("% d", & N )! = EOF) {for (I = 1; I <= N; I ++) for (j = 1; j <= N; ++ J) scanf ("% d", & map [I] [J]); printf ("% d \ n", km ();} return 0 ;}
Minimum weight matching
/* Poj 2195 going home learns bipartite graph matching, So it uses the minimum weight to match some sides, it is faster than the minimum cost and the maximum flow. Some minimum and maximum weight matching are similar. You only need to obtain the opposite number of edge weights. Then, the process is the same as the maximum weight matching. The last edge weight is a negative number and the opposite is obtained. the number is enough */# include <iostream> # include <cmath> using namespace STD; int M, N; struct node // represents the position of a person or house {int X, Y ;}; struct edge // saves the edge in an adjacent table {int V, F, next ;} E [100000]; node * Man, * house; // int * match, * lx, * ly, * slack, * visx, * visy, * head, nman; // match X's top Mark y's top Mark optimized array x access flag y access flag number of adjacent header node persons char map [110] [110]; int Hu Ngray (int I) // Hungarian algorithm {Int J, V; visx [I] = 1; for (j = head [I]; J! =-1; j = E [J]. next) {v = E [J]. v; If (visy [v]) continue; If (LX [I] + ly [v] = E [J]. f) {visy [v] = 1; if (Match [v] =-1 | hungray (Match [v]) {match [v] = I; return 1 ;}} else if (Slack [v]> lx [I] + ly [v]-E [J]. f) slack [v] = Lx [I] + ly [v]-E [J]. f;} return 0;} int km () // km {memset (match,-1, sizeof (INT) * nman); int I, j, D; memset (ly, 0, sizeof (INT) * nman); for (I = 0; I <nman; ++ I) {for (j = 0; j <nman; ++ J) slack [J] = 0x7fffffff; while (1) {memset (visx, 0, sizeof (INT) * nman ); Memset (visy, 0, sizeof (INT) * nman); If (hungray (I) break; D = 0x7fffffff; For (j = 0; j <nman; ++ J) if (! Visy [J] & slack [J] <D) d = slack [J]; for (j = 0; j <nman; ++ J) {If (visx [J]) lx [J]-= D; If (visy [J]) ly [J] + = D; else slack [J]-= D ;}} D = 0; for (I = 0; I <nman; ++ I) d ++ = Lx [I], d + = ly [I]; Return-D; // returns the opposite number} int main () {int I, j, Yong; while (CIN> N> m, m + n) {nman = 0; // initialize Yong = 0; for (I = 0; I <n; ++ I) // read data for (j = 0; j <m; ++ J) {CIN> map [I] [J]; If (Map [I] [J] = 'M') nman ++ ;} match = new int [nman]; // apply for space man = new node [nman]; // House = new node [nman]; // Lx = new int [nman]; // Ly = new int [nman]; // slack = new int [nman]; // visx = new int [nman]; // visy = new int [nman]; // head = new int [nman]; // int jman = 0, jhouse = 0; for (I = 0; I <n; ++ I) // The location of the statistician and house for (j = 0; j <m; ++ J) {If (Map [I] [J] = 'M ') {MAN [jman]. X = I; man [jman ++]. y = J;} else if (Map [I] [J] = 'H') {House [jhouse]. X = I; House [jhouse ++]. y = J ;}} memset (Head,-1, sizeof (INT) * nman); // distance between a computer and a house edge building for (I = 0; I <nman; ++ I) {int max =-(0x7fffffff); // assign a value to the LX array during calculation, that is, the maximum right of the edge connected to I (j = 0; j <nman; ++ J) {e [Yong]. V = J; E [Yong]. F =-(ABS (MAN [I]. x-House [J]. x) + ABS (MAN [I]. y-House [J]. y); // If (max <E [Yong]. f) max = E [Yong]. f; // update MaxE [Yong]. next = head [I]; head [I] = Yong ++;} lx [I] = max; // assign a value to lx} cout <km () <Endl; // computing output Delete [] match; // release space Delete [] Man; Delete [] House; Delete [] lx; Delete [] ly; Delete [] slack; delete [] visx; Delete [] visy; Delete [] Head;} return 0 ;}