HDU 2255 奔小康赚大钱
题目分析:这个是个KM的模板题。
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #include<queue> #include<cmath> using namespace std; #define INF 0x3fffffff #define maxn 1255 int n;///房子的数量 int G[maxn][maxn];///所构造的邻接矩阵 int Lx[maxn], Ly[maxn];///二分图的可行性顶标 bool vx[maxn], vy[maxn];///判断这个点是否在本次匹配中出现过 int P[maxn], d; bool Find(int u) { vx[u] = true; for(int i=1; i<=n; i++) { if(!vy[i] && Lx[u] + Ly[i] == G[u][i]) { vy[i] = true; if(P[i] == -1 || Find(P[i])) { P[i] = u; return true; } } if(!vy[i]) d = min(d, Lx[u] + Ly[i] - G[u][i]); } return false; } int solve() { memset(P, -1, sizeof(P)); for(int i=1; i<=n; i++) { while(1) { d = INF;///初始化成一个极大值 memset(vx, false, sizeof(vx)); memset(vy, false, sizeof(vy)); if( Find(i) )///判断i点是否找到合适的匹配对象 break; for(int i=1; i<=n; i++) { if(vx[i]) Lx[i] -= d; if(vy[i]) Ly[i] += d; } } } int ans = 0; for(int i=1; i<=n; i++) ans += G[P[i]][i]; return ans; } int main() { while(scanf("%d", &n) != EOF) { memset(Lx, 0, sizeof(Lx)); memset(Ly, 0, sizeof(Ly)); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { scanf("%d", &G[i][j]); Lx[i] = max(Lx[i], G[i][j]);///Lx[i] 保存 i点所能存储的最大值 } } printf("%d\n", solve() ); } return 0; }