Problem Solving Ideas:
Binary graph with right matching, card cost flow, using km algorithm.
#include <cstring> #include <algorithm> #include <cstdio> #include <iostream>using namespace std;/* km algorithm * complexity O (nx*nx*ny) * For maximum weight matching * If minimum weight matching is obtained, the weights can be reversed, resulting in the opposite number * point number starting from 0 */const int maxn = 310;const int INF = 0 X3f3f3f3f;int nx,ny;//on both sides of the int g[maxn][maxn];//two-dimensional graph describes the matching state of the points in int linker[maxn],lx[maxn],ly[maxn];//y, the dot designator int in x, y 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;} int main () {int n; while (scanf ("%d", &n) = = 1) {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;}
HDU 2255 Ben-off, make a lot of money (km algorithmic templates)