uva 11383 Golden Tiger Claw
题目大意:给定一个N×N的矩阵,每个格子里都有一个正整数
w(i,j)
。你的任务是给每行确定一个整数row(i), 每列也确定一个整数
col(i)
,使得对于格子
(i,j)
,
w(i,j)<=row(i)+col(j)
。所有
row(i)
和
col(j)
的总和最小。
解题思路:KM算法。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
const int N = 5000;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int n;
int W[N][N];
int Lx[N], Ly[N];
int left[N];
bool S[N], T[N];
bool match(int i) {
S[i] = true;
for (int j = 1; j <= n; j++) {
if (Lx[i] + Ly[j] == W[i][j] && !T[j]) {
T[j] = true;
if (!left[j] || match(left[j])) {
left[j] = i;
return true;
}
}
}
return false;
}
void update() {
int a = INF;
for (int i = 1; i <= n; i++) {
if (!S[i]) continue;
for (int j = 1; j <= n; j++) {
if (T[j]) continue;
a = min(a, Lx[i] + Ly[j] - W[i][j]);
}
}
for (int i = 1; i <= n; i++) {
if (S[i]) Lx[i] -= a;
if (T[i]) Ly[i] += a;
}
}
void KM() {
for (int i = 1; i <= n; i++) {
left[i] = Lx[i] = Ly[i] = 0;
for (int j = 1; j <= n; j++) {
Lx[i] = max(Lx[i], W[i][j]);
}
}
for (int i = 1; i <= n; i++) {
while (1) {
for (int j = 1; j <= n; j++) S[j] = T[j] = 0;
if (match(i)) break;
else update();
}
}
}
void input() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &W[i][j]);
}
}
}
int main() {
while (scanf("%d", &n) != EOF) {
input();
KM();
int sum = Lx[1];
printf("%d", Lx[1]);
for (int i = 2; i <= n; i++) {
printf(" %d ", Lx[i]);
sum += Lx[i];
}
puts("");
printf("%d", Ly[1]);
sum += Ly[1];
for (int i = 2; i <= n; i++) {
printf(" %d", Ly[i]);
sum += Ly[i];
}
printf("\n%d\n", sum);
}
return 0;
}