"SinGuLaRiTy-1018" Copyright (c) SinGuLaRiTy 2017. All rights Reserved.
Some Method is reproduced from Evasiu.
The basic steps of the KM algorithm
(1) Initialization of feasible benchmarks
(2) Searching for complete match with Hungarian algorithm
(3) Modify the feasible benchmark if no complete match is found
(4) Repeat (2) (3) until a complete match is found for the equal sub-graph
Related concepts
KM algorithm is used to find the best matching algorithm with weighted binary graph.
A binary chart is a graph in which all vertices can be divided into two sets: X and Y, where any two of x and Y are not connected in the same set of points, and vertices from the X-set are wired to vertices from the Y-set. When these lines are assigned to a certain weight, such a binary graph is a weighted two-part graph.
Binary graph matching is to find a set of edges, where the vertices are in two sets, and any two edges do not have the same vertex, this group of edges is called a binary graph matching, and the maximum number of edges can be obtained, called the maximum match of the binary graph.
<Tip> We can also look at the maximum matching of the binary graph, that is, the default weight of each side of the two graphs is 1, and we find the maximum matching weights of the binary graphs. For the weighted binary graph, the edge has a weight greater than 0, find a set of matches, make it the most weight, that is, the best match with the weighted binary graph.
Hungarian algorithm
The Hungarian algorithm is generally used to find the maximum matching of a binary graph. The algorithm chooses the side of the binary graph according to certain rules to join the matching sub-graph, and its basic mode is:
Initialize matching sub-graph to null
While the augmented path can be found
Do add the augmented path to the matching sub-graph
Characteristics of Augmented path augmentation paths
There are odd strips of edges
Beginning on x side of the dichotomy, end point on the Y side of the binary graph
The points on the path must be one on the X side, one on the Y side, interlaced
There are no duplicate points on the entire path
The start and end points are not currently paired, and the other points are already in the matching sub-graph
All the odd edges on the path are not currently on the edge of the current matching sub-graph, and all the even-odd bars have entered the current matching sub-graph. An odd edge is one edge more than an even edge
So when we add all of the odd-number edges to the matching sub-graph and delete the strip edges, the number of matches increases by 1.
Implementation process
For example, the blue is the current matching sub-graph, currently only the Edge x0y0, and then through X1 found the augmented path: x1y0->y0x0->x0y2
The first and the odd first edges x1y0 and x0y2 are not in the current matching sub-graph, and the number of the x0y0 is in the matching sub-graph, by adding x1y0 and x0y2 to the matching sub-graph and removing x0y0, the match count is increased from 1 to 2. Each time an augmented path is found, by adding a delete edge, we can always add 1 to the number of matches.
There are two ways to find the augmented path, one is DFS and one is BFS. For example, from X2 to find the augmented path, if it is deep search, X2 find y0 match, but found that y0 has been X1 match, so go deep to X1, to find a new matching node x1, the results found no other matching nodes, so the match failed, X1 then find x2, found Y1 can match, The new augmented path was found. If it is wide search, X1 find y0 node, because can not immediately get a legitimate match, so it as a candidate into the queue, and then find Y1, because Y1 has been matched, so the match successfully returned. Relatively speaking, the deep search to be easy to understand, its stack can be maintained by the recursive process, while the wide search will need to maintain a queue, and on the way over the route to do their own marking, to achieve a more troublesome.
For a binary graph with weights, we can think of it as a binary graph of all the vertices of the X set to all the vertices of the Y-set (adding the previously absent edges into a binary graph with a weight of 0), meaning that it must have a complete match (that is, its match number is min (| x|,| y|) )。 In order to maximize the weight, we actually choose the edge by the greedy algorithm, forming a new binary graph (we call it a two-molecule map), and on the basis of the binary map to find the maximum match, when the maximum match is a complete match, we can determine that the match is the best match. (Here we define the maximum match: match and best match with the maximum number of matched edges: the weight of the matched edge and the maximum match.) )
The greedy algorithm always adds the optimal edge to the two-molecule graph, and the optimal edge will bring the greatest contribution to the current matching sub-graph, and the measure of contribution is achieved by benchmarking. Below we will explain this process in an example.
With the right two-part diagram:
The algorithm converts weights to benchmarks, and each vertex of the X-set and Y-sets has a benchmark value, and the weights are all placed on the X-set in the initial case. Since each vertex will have at least one matching point, the greedy algorithm must first select the most weighted edge on the vertex (ideally, these edges have no intersection, so we naturally get the best match). The initial two molecular figure is: (you can see that the X-benchmark is the maximum weight on the vertex at initialization, and the Y-benchmark is 0)
Find the augmented path from the X0, find the X0y4, from X1 can not find the augmented path, that is, you must add a new edge to the two molecular diagram, so that X1 to find its match, at the same time the sum of the weights added maximum. Since X1 to Y4 and Y4 has been X0 matched, there are two possible, one is to find a new match for X0 and Y4 to X1, or to find a new match for X1, now we will see the role of the benchmark. According to the traditional algorithm description, the condition of being able to enter the edge of the two molecular graph is L (x) +l (y) >=weight (XY). When an augmented path is not found, the X-vertex set on the searched path is set to S,y-T, and for all points in S and points not in T YJ, d=min{(L (xi) +l (YJ)-weight (XIYJ)} is computed, Subtract d from the X benchmark in the S-set and add it to the benchmark of y in the T-set, because the X-benchmark in the S-set is reduced, and the Y-benchmark in T is not the same, which is equivalent to the two sets of L (x) +l (y) smaller, that is, a new edge can be added to the two From the greedy side of the edge, we can choose a new edge for the X0 to discard the original two molecular map of the matching edge, you can also choose a new edge for X1 and discard the original two molecular map of the matching edge, because we can not select both X0y4 and X1y4, because this is an illegal match, this time, d=min{(L (xi) The meaning of +l (YJ)-weight (XIYJ)} is that we select a new edge, which will be added to the matching sub-graph so that the matching is valid, select this edge to form the matched sub-graph, The weight of the illegally matched sub-graph, which is the same as the original matching sub-graph plus this illegal edge, and (if it is legal, it will be the largest) is the smallest, that is, the maximum weight. A good wound. To express in a mathematical way, set the original illegal match (its weight is the largest, because we always find from the weight of the largest side) of the weight of W, the new legal match for W ', D for Min{w-w ' I}. In this example, S={x0, x1},y={y4}, find the minimum d=l (X1) +l (Y0)-weight (x1y0) = 2 to get a new two molecular diagram:
Re-X1 search for the augmented path, find the x1y0, you can see the new matching sub-graph weight of 9+6=15, than the original illegal matching weight 9+8=17 just less d=2.
Next, you cannot find the augmented path from X2, and the path it walks through is shown as a blue route. The resulting illegal matching sub-graph: x0y4,x1y0 and x2y0 weights and is 22. On this path, if a new match is found for any of the vertices in s={x0,x1,x2}, the problem can be resolved and then the D is started.
D=l (X0) +l (Y2)-weight (x0y2) =l (X2) +l (Y1)-weight (x2y1) =1.
The new two molecular chart is:
Re-searching for the augmented path for X2, if we are using deep search, we will get the path: X2y0->y0x1->x1y4->y4x0->x0y2, that is, the odd bar edge and delete the even number of edges, the new matching sub-graph from these vertices to get the new weight of 21 If you are using a wide search, you will get the path x2y1, and the original two matching edges with a weight of 21. Suppose we are using a wide search, and the resulting new matching sub-graph is:
Next, and so on, until a match point is found for X4.
The biggest feature of the KM algorithm is the use of benchmarks and weights to generate a two-molecule graph, finding the maximum match on the two molecular map, and when only a complete match is found, the best match can be obtained. The role of benchmarking and weighting is to limit the addition of new edges, so that new edges added will always be able to add matching numbers to the sub-graph, while at the same time make the weight and the maximum increase.
Implementation code
/*HDU-2255*/#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#defineMAXN 310#defineINF 0x3f3f3f3fusing namespacestd;intNx,ny;intG[MAXN][MAXN];intLINKER[MAXN],LINKX[MAXN],LINKY[MAXN];intSLACK[MAXN];BOOLVISX[MAXN],VISY[MAXN];BOOLDfsintk) {Visx[k]=true; for(inty=0; y<ny;y++) { if(Visy[y])Continue; inttmp=linkx[k]+linky[y]-G[k][y]; if(!tmp) {Visy[y]=true; if(linker[y]==-1||DFS (Linker[y])) {Linker[y]=K; return true; } } Else if(slack[y]>tmp) Slack[y]=tmp; } return false;}intKM () {memset (linker,-1,sizeof(linker)); memset (Linky,0,sizeof(Linky)); memset (Linkx,-inf,sizeof(Linkx)); for(intI=0; i<nx;i++) { for(intj=0; j<ny;j++) { if(g[i][j]>Linkx[i]) linkx[i]=G[i][j]; } } for(intx=0; x<nx;x++) { for(intI=0; i<ny;i++) Slack[i]=INF; while(true) {memset (VISX,false,sizeof(VISX)); memset (Visy,false,sizeof(Visy)); if(dfs (x) = =true) Break; intD=INF; for(intI=0; i<ny;i++) if(!visy[i]&&d>Slack[i]) d=Slack[i]; for(intI=0; i<nx;i++) { if(Visx[i]) linkx[i]-=D; } for(intI=0; i<ny;i++) { if(Visy[i]) linky[i]+=D; ElseSlack[i]-=D; } } } intres=0; for(intI=0; i<ny;i++) if(linker[i]!=-1) Res+=G[linker[i]][i]; returnRes;}intMain () {intN; while(SCANF ("%d", &n)! =EOF) { for(intI=0; i<n;i++) for(intj=0; j<n;j++) scanf ("%d",&G[i][j]); NX=ny=N; printf ("%d\n", KM ()); } return 0;}
time:2017-07-05
[SinGuLaRiTy] KM algorithm