1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| #include <iostream> #include <cstring> #include <cstdio>
using namespace std; const int MAXN = 305; const int INF = 0x3f3f3f3f;
int love[MAXN][MAXN]; int ex_girl[MAXN]; int ex_boy[MAXN]; bool vis_girl[MAXN]; bool vis_boy[MAXN]; int match[MAXN]; int slack[MAXN];
int N;
bool dfs(int girl) { vis_girl[girl] = true;
for (int boy = 0; boy < N; ++boy) {
if (vis_boy[boy]) continue;
int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];
if (gap == 0) { vis_boy[boy] = true; if (match[boy] == -1 || dfs( match[boy] )) { match[boy] = girl; return true; } } else { slack[boy] = min(slack[boy], gap); } }
return false; }
int KM() { memset(match, -1, sizeof(match)); memset(ex_boy, 0, sizeof(ex_boy));
for (int i = 0; i < N; ++i) { ex_girl[i] = love[i][0]; for (int j = 1; j < N; ++j) { ex_girl[i] = max(ex_girl[i], love[i][j]); } }
for (int i = 0; i < N; ++i) {
fill(slack, slack + N, INF);
while (1) {
memset(vis_girl, false, sizeof(vis_girl)); memset(vis_boy, false, sizeof(vis_boy));
if (dfs(i)) break;
int d = INF; for (int j = 0; j < N; ++j) if (!vis_boy[j]) d = min(d, slack[j]);
for (int j = 0; j < N; ++j) { if (vis_girl[j]) ex_girl[j] -= d;
if (vis_boy[j]) ex_boy[j] += d; else slack[j] -= d; } } }
int res = 0; for (int i = 0; i < N; ++i) res += love[ match[i] ][i];
return res; }
int main() { while (~scanf("%d", &N)) {
for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) scanf("%d", &love[i][j]);
printf("%d\n", KM()); } return 0; }
|