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() {
//初始时为了使Lx[i]+Ly[j]>=W[i, j]恒成立,令Lx[i]为所有与顶点Xi关联的边的最大权,Ly[j]=0
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;
}
版权声明:本文为博主原创文章,未经博主允许不可转载。
时间: 2024-12-23 11:11:47