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

UVA 11383 Golden Tiger Claw(最佳二分图完美匹配)

2013-09-01 12:31 369 查看
题意:在一个N*N的方格中,各有一个整数w(i,j),现在要求给每行构造row(i),给每列构造col(j),使得任意w(i,j)<=row(i)+col(j),输出row(i)与col(j)之和最小的方案。

当看到w(i,j)<=row(i)+col(j),并且row()col()都是自己构造的时候,就想到了二分匹配:w[i,j]<=Lx[i]+Ly[j]。直接套用模板,求最佳二分完美匹配,输出Lx[],Ly[],以及最小值即可。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define clr(a,m) memset(a,m,sizeof(a))
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

const int MAXN=555;
const int INF =1e9;
const double eps=1e-10;

int gap[MAXN][MAXN];
int Lx[MAXN],Ly[MAXN],slack[MAXN];
int left[MAXN],n;
bool S[MAXN],T[MAXN];

void read()
{
rep(i,1,n)
rep(j,1,n)
scanf("%d",&gap[i][j]);
}

bool match(int u)
{
S[u]=true;
rep(v,1,n)
if(!T[v]){
int tmp=Lx[u]+Ly[v]-gap[u][v];
if(tmp==0){
T[v]=true;
if(!left[v]||match(left[v])){
left[v]=u;
return true;
}
}else slack[v]=min(slack[v],tmp);
}
return false;
}

void update()
{
int a=INF;
rep(v,1,n)
if(!T[v])
a=min(a,slack[v]);
rep(i,1,n){
if(S[i])Lx[i]-=a;
if(T[i])Ly[i]+=a;
}
}

void KM()
{
rep(i,1,n){
left[i]=Ly[i]=0;
Lx[i]=-INF;
rep(j,1,n)
Lx[i]=max(Lx[i],gap[i][j]);
}
rep(i,1,n){
rep(j,1,n)
slack[j]=INF;
while(1)
{
rep(j,1,n)
S[j]=T[j]=0;
if(match(i))
break;
else
update();
}
}
}

void print()
{
int ans=0;
rep(i,1,n){
ans+=Lx[i];
if(i!=1)printf(" ");
printf("%d",Lx[i]);

}
printf("\n");
rep(i,1,n){
ans+=Ly[i];
if(i!=1)printf(" ");
printf("%d",Ly[i]);
}
printf("\n");
printf("%d\n",ans);
}

int main()
{
while(~scanf("%d",&n))
{
read();
KM();
print();
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: