您的位置:首页 > 其它

UVA11383 二分图最佳匹配的性质的应用

2014-04-03 22:58 260 查看
/*UVA11383
二分图最佳匹配的性质的应用
首先看这道题的题面:
给定一个N*N的矩阵,每个格子上填上权值W[i][j];
现在要求找到row[1]..row
,和col[1]...col
。分别对应每一行和每一列。
使得对于任意格子(i,j),W[i][j]<=row[i]+col[j]
还要求出row[i]和col[i]总和的最小值
而最优匹配(二分后的权值和最大)后,顶标数组会满足Lx(x)+Ly(y)>=W[x][y]这个条件,而sigm(Lx(i)+Ly(j))是最小的。
*/
#include <cmath>
#include <algorithm>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stack>
#include <set>
#include <map>
#include <vector>
#define typed int
#define INF 1<<30
#define maxn 550
#define eps 1e-6
using namespace std;
int n;
typed W[maxn][maxn];
typed Lx[maxn],Ly[maxn];//顶标
int lef[maxn];//由A到B的映射
bool S[maxn],T[maxn];

bool match(int i){
S[i]=true;
for(int j=1;j<=n;j++) if (fabs(Lx[i]+Ly[j]-W[i][j])<eps && !T[j]){
T[j]=true;
if (!lef[j] || match(lef[j])){
lef[j]=i;
return true;
}
}
return false;
}

void update(){
typed a=INF;
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++){
lef[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++){
for(;;){
for(int j=1;j<=n;j++) S[j]=T[j]=false;
if (match(i)) break;else update();
}
}
}
int nextint(){
int x;
scanf("%d",&x);
return x;
}
void read(){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
W[i][j]=nextint();
}
void printans(){
for(int i=1;i<=n;i++)
if (i<n) printf("%d ",Lx[i]);else printf("%d\n",Lx[i]);
for(int i=1;i<=n;i++)
if (i<n) printf("%d ",Ly[i]);else printf("%d\n",Ly[i]);
int sum=0;
for(int i=1;i<=n;i++) sum+=Lx[i]+Ly[i];
printf("%d\n",sum);
}
int main(){
while(cin>>n){
read();
KM();
printans();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: