您的位置:首页 > 编程语言 > Go语言

UVa11383 Golden Tiger Claw ( KM )

2013-02-01 21:57 288 查看
这是一道二分匹配的副产品题目,题目: N*N的矩阵,每个个格子里面有一个数,w[i][j], 给每一行和每一列分别赋给一个值,使得对于任意格子都有,w[i][j] <= row[i] + col[j];

要求输出row和col,以及它们的总和的最小值

由于KM算法结束后,所有顶标之和就是最小的,这道题没有求最小匹配的值,而是求的可行顶标的值

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn = 505;
int w[maxn][maxn], n;
int Lx[maxn], Ly[maxn];
int left[maxn];
bool s[maxn], t[maxn];

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 = 1 << 30;
for ( int i = 1; i <= n; ++i ) if ( s[i] )
for ( int j = 1; j <= n; ++j ) if ( !t[j] )
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();
}
}
}

int main()
{
while ( scanf("%d", &n) != EOF ) {
for ( int i = 1; i <= n; ++i )
for ( int j = 1; j <= n; ++j ) scanf("%d", &w[i][j]);
KM();
int ans = 0;
ans += Lx[1];
printf("%d", Lx[1]);
for ( int i = 2; i <= n; ans += Lx[i++] ) printf(" %d", Lx[i]);
printf("\n%d", Ly[1]);
ans += Ly[1];
for ( int i = 2; i <= n; ans += Ly[i++] ) printf(" %d", Ly[i]);
printf("\n%d\n", ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: