Hdu2255 running well to make big money, maximum right matching, KM algorithm, hdu 2255km
Click Open Link
Max Weight Matching
KM Algorithm
Algorithm steps:
Set the top mark of vertex Xi to a [I], and the top mark of vertex Yi to B [I]
I. initially, a [I] is the maximum weight of the edge associated with Xi, B [j] = 0, ensure that a [I] + B [j]> = w (I, j) is true
Ii. When the equal subgraph does not contain a complete match, modify the top mark to expand the equal subgraph until a complete match is found.
Iii. Methods for modifying the top mark
After finding the staggered path from Xi, a tree is generated, and all its leaf nodes are X nodes, which reduces the D value for the top mark of X vertices in the staggered tree, D value is added to the top mark of Y vertex. For all edges (I, j) in the graph ),
You can see:
Neither I nor j is in the staggered tree, And the edge (I, j) is still not an equal subgraph.
Both I and j are in the staggered tree, And the edge (I, j) still belongs to the same subgraph.
I is not in the staggered tree. j is in the staggered tree. a [I] + B [j] expands, and edge (I, j) does not belong to an equal subgraph.
I is in the staggered tree, j is not in the staggered tree, and edge (I, j) may be added to an equal subgraph.
To ensure that a [I] + B [j]> = w (I, j) is always valid, and at least one edge is added to an equal subgraph, d = min {a [I] + B [j]-w (I, j)}, I is in the staggered tree, j is not in the staggered tree
Time Complexity:You need to find the O (n) Increment path. You need to modify the O (n) Increment path at most. During each increment, the enumeration edge is used to evaluate the D value. The complexity is O (n2 ), the total complexity is O (n4 ). simple optimization can be reduced to O (n3). Each Y vertex has a "relaxation volume" function slack, Which is initialized to an infinite number every time the augmented path is searched. When you check the edge (I, j) in the process of searching for the augmented path, if it is not in the same subgraph, the slack [j] is converted into A smaller value of the original value and A [I] + B [j]-w [I, j. In this way, the minimum value of the slack value of all Y vertices not in the staggered tree can be used as the D value when the top mark is modified. Note that after the top mark is modified, all slack values must be subtracted from d.
# Include <cmath> # include <cstdio> # include <cstring> # include <iostream> # include <algorithm> # include <set> # include <map> # include <stack> # include <queue> # include <vector> # include <string> # define for0 (, b) for (a = 0; a <B; ++ a) # define for1 (a, B) for (a = 1; a <= B; ++) # define foru (I, a, B) for (I = a; I <= B; ++ I) # define ford (I, a, B) for (I = a; I> = B; -- I) using namespace std; typedef long ll; const int maxn = 310; const int IN F = 1e9;/* KM algorithm * O (nx * ny) * Find the maximum weight match * If the minimum weight match is obtained, the opposite number of weights can be obtained, returns the opposite number. */Int nx, ny; int g [maxn] [maxn]; int linker [maxn], lx [maxn], ly [maxn]; // The matching status of each point in y, int slack [maxn]; bool visx [maxn], visy [maxn]; bool DFS (int x) {visx [x] = true; for (int y = 0; y <ny; ++ y) {if (visy [y]) continue; int tmp = lx [x] + ly [y]-g [x] [y]; if (tmp = 0) {visy [y] = true; if (linker [y] =-1 | DFS (linker [y]) {linker [y] = x; return true ;}} else if (slack [y]> tmp) slack [y] = tmp;} return false;} Int KM () {memset (linker,-1, sizeof linker); memset (ly, 0, sizeof ly); for (int I = 0; I <nx; ++ I) {lx [I] =-INF; for (int j = 0; j <ny; ++ j) if (g [I] [j]> lx [I]) lx [I] = g [I] [j];} for (int x = 0; x <nx; ++ x) {for (int I = 0; I <ny; ++ I) slack [I] = INF; while (true) {memset (visx, false, sizeof visx); memset (visy, false, sizeof visy); if (DFS (x) break; int d = INF; for (int I = 0; I <ny; ++ I) if (! Visy [I] & d> slack [I]) d = slack [I]; for (int I = 0; I <nx; ++ I) if (visx [I]) lx [I]-= d; for (int I = 0; I <ny; ++ I) {if (visy [I]) ly [I] + = d; else slack [I]-= d ;}} int res = 0; for (int I = 0; I <ny; ++ I) if (linker [I]! =-1) res + = g [linker [I] [I]; return res;} // HDU 2255int main () {# ifndef ONLINE_JUDGE freopen ("in. cpp "," r ", stdin); freopen (" out. cpp "," w ", stdout); # endif // ONLINE_JUDGE int n; while (~ Scanf ("% d", & n) {for (int I = 0; I <n; ++ I) for (int j = 0; j <n; + + j) scanf ("% d", & g [I] [j]); nx = ny = n; printf ("% d \ n ", KM ();} return 0 ;}
Will be km algorithm, and will use matlab to calculate the optimal matching help, it is best to understand Programming
KM algorithm: in fact, it seems that its most basic idea is to gradually approach the optimal matching, and each time taking the smallest step toward the most matching until the optimum is reached (to the end, sigma (lx [I] + ly [I]) is exactly equal to the optimal matching value)
Algorithm, initialize LX [I] as the maximum edge weight of equi. LY [I] is initially 0, at this time, if the maximum weighted edge endpoint corresponding to each fixed point does not overlap, it is clear that the current matching condition is both optimal.
The top mark (LX [I], LY [I]) value is constantly updated to match the algorithm.
If you find the augmented path, continue to find the next vertex. If you cannot find it, change the current top tag value because (sigma (lx [I] + ly [I]) it is the estimated value of the optimal match. If the matching of the current node cannot be found, it indicates that the current optimal match cannot be achieved and needs to be adjusted, the core of the KM algorithm is how to implement an effective and correct adjustment method.
It is necessary to gradually approach the answer with the smallest adjustment. Second, you need to know which top labels to adjust. First, adjustment cannot damage the current matching condition (because the matching is implemented in the search for the augmented path)
: KM algorithm pascal program
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 the find
# Include <cstdio>
# Include <cstring>
Using namespace std;
Const int maxn = 160, OO = 2147483647;
Int w [maxn] [maxn];
Int lx [maxn], ly [maxn];
Int linky [maxn];
Int visx [maxn], visy [maxn];
Int N;
Int slack [maxn];
Void input (){
Scanf ("% d", & N );
For (int I = 0; I <N; ++ I)
For (int j = 0; j <N; ++ j)
Scanf ("% d", & w [I] [j]);
}
Bool find (int x ){
Visx [x] = true;
For (int y = 0; y <N; ++ y ){
If (visy [y]) continue;
Int t = lx [x] + ly [y]-w [x] [y];
If (t = 0 ){
Visy [y] = true;
If (linky [y] =-1 | find (linky [y]) {
Linky [y] = x;
Return true;
... The remaining full text>