链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2255
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 550 #define INF 0x3f3f3f3f int n; int G[N][N], lx[N], ly[N];//x集合的顶标 int visx[N], visy[N], s[N], used[N];//s是为了找d, visx[i]x中的i有没有被增广过 bool Find(int u)//增广路 { visx[u] = 1; for(int i=1; i<=n; i++) { if(!visy[i] && lx[u]+ly[i]==G[u][i]) { visy[i]=1; if(!used[i] || Find(used[i])) { used[i] = u; return true; } } else s[i] = min(s[i], lx[u]+ly[i]-G[u][i]); } return false; } int KM() { memset(used, 0, sizeof(used)); memset(lx, 0, sizeof(lx)); memset(ly, 0, sizeof(ly)); for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) lx[i] = max(lx[i], G[i][j]); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) s[j] = INF; while(1) { memset(visx, 0, sizeof(visx)); memset(visy, 0, sizeof(visy)); if(Find(i)) break; int d = INF; for(int j=1; j<=n; j++) if(!visy[j]) d = min(d, s[j]); for(int j=1; j<=n; j++) { if(visx[j]) lx[j] -= d; if(visy[j]) ly[j] += d; } } } int res=0; for(int i=1; i<=n; i++) res += G[used[i]][i]; return res; } int main() { while(scanf("%d", &n)!=EOF) { int i, j; memset(G, 0, sizeof(G)); for(i=1; i<=n; i++) for(j=1; j<=n; j++) scanf("%d", &G[i][j]); printf("%d\n", KM()); } return 0; }
勿忘初心