码迷,mamicode.com
首页 > 其他好文 > 详细

UVA 11383 KM性质

时间:2016-04-29 15:14:25      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:

点击打开链接

题意:一个n*n的矩阵每个格子里有一个正整数w(i,j)你的任务是确定每行一个整数row(i)每列一个整数col(i),对每个格子都有w(i,j)<=row(i)+col(j)所有row(i)和col(i)和尽量小。

思路:本题利用KM算法l(x)+l(y)>=w(x,y)的性质直接可以知道得出的顶标之和即为最小的。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
const int INF=0x3f3f3f3f;
using namespace std;
int s[505][505],visx[505],visy[505],match[505];
int lx[505],ly[505];
int n,m;
int hungarian(int x){
    int i;
    visx[x]=1;
    for(i=1;i<=m;i++){
        if(!visy[i]&&lx[x]+ly[i]==s[x][i]){
            visy[i]=1;
            if(!match[i]||hungarian(match[i])){
                match[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int KM(){
    int i,j,k,sum,temp;
    sum=0;
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));
    memset(match,0,sizeof(match));
    for(i=1;i<=n;i++)
    for(j=1;j<=m;j++)
    lx[i]=max(lx[i],s[i][j]);
    for(i=1;i<=n;i++){
        while(1){
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(hungarian(i))
            break;
            else{
            temp=INF;
            for(j=1;j<=n;j++)
            if(visx[j]){
                for(k=1;k<=m;k++)
                if(!visy[k])
                temp=min(temp,lx[j]+ly[k]-s[j][k]);
            }
            if(temp==INF)
            return -1;
            for(j=1;j<=n;j++)
            if(visx[j])
            lx[j]-=temp;
            for(j=1;j<=m;j++)
            if(visy[j])
            ly[j]+=temp;
            }
        }
    }
    for(i=1;i<=m;i++)
    if(match[i]!=0){
    if(s[match[i]][i]!=-INF)
    sum+=s[match[i]][i];
    else
    return -1;
    }
    return sum;
}
int main(){
    int i,j,a,b,c,ans,num;
    while(scanf("%d",&n)!=EOF){
        m=n;
        for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        s[i][j]=-INF;
        for(i=1;i<=n;i++)
        for(j=1;j<=m;j++){
        scanf("%d",&num);
        s[i][j]=num;
        }
        ans=KM();
        for(i=1;i<=n;i++)
        printf("%d ",lx[i]);
        printf("\n");
        for(i=1;i<=m;i++)
        printf("%d ",ly[i]);
        printf("\n");
        printf("%d\n",ans);
    }
    return 0;
}


UVA 11383 KM性质

标签:

原文地址:http://blog.csdn.net/dan__ge/article/details/51277493

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!