int n;
int weight[maxn][maxn];
int lx[maxn],ly[maxn];
bool sx[maxn],sy[maxn];
int match[maxn];
bool path(int x){ //求增广路
sx[x]=true;
for(int y=1;y<=n;y++){
if(!sy[y]&&lx[x]+ly[y]==weight[x][y]){
sy[y]=true;
if(match[y]==-1||path(match[y])){
match[y]=x;
return true;
}
}
}
return false ;
}
int KM(bool max_weight){
if(!max_weight){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
weight[i][j]=-weight[i][j];
}
}
}
for(int i=1;i<=n;i++){
ly[i]=0;
lx[i]=-INF;
for(int j=1;j<=n;j++){
if(lx[i]<weight[i][j]){
lx[i]=weight[i][j];
}
}
}
memset(match,-1,sizeof(match));
for(int i=1;i<=n;i++){
while(1){
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
if(path(i)){
break;
}
int inc=INF;
for(int i=1;i<=n;i++){
if(sx[i]){
for(int j=1;j<=n;j++){
if(!sy[j]&&(lx[i]+ly[j]-weight[i][j])<inc)
inc=lx[i]+ly[j]-weight[i][j];
}
}
}
if(inc==0)return -1;
for(int i=1;i<=n;i++){
if(sx[i])
lx[i]-=inc;
if(sy[i])
ly[i]+=inc;
}
}
}
int sum=0;
for(int i=1;i<=n;i++){
if(match[i]>=0)
sum+=weight[match[i]][i];
}
if(!max_weight){
sum=-sum;
}
return sum;
}
void solve()
{
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
scanf("%d",&weight[i][j]);
}
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
printf("%d\n",KM(1));
}
}
KM模板
最新推荐文章于 2020-02-22 11:54:09 发布