poj 2594(二分图最优匹配)

#include<iostream>//0(n^4)最小权匹配,KM算法
#include<stdio.h>
using namespace std;
struct node
{
    int row;
    int column;
}man[10002],home[10002];
int row,column,NumMan,NumHome;
int w[102][102],lx[102],ly[102],matchy[102];
bool visitx[102],visity[102];
bool  dfs(int u)
{
    int v;
    visitx[u]=true;
    for(v=1;v<=NumHome;v++)
    {
        if(visity[v]==false&&lx[u]+ly[v]==w[u][v])
        {
            visity[v]=true;
           
            if(matchy[v]==0||dfs(matchy[v])==true)
            {
                    matchy[v]=u;
                        return true;
   
       
            }   
        }
    }
    return false;
}
int main()
{
    int total;
    int min;
    int i,j,k;
    char ch;
    while(scanf("%d %d",&row,&column),row&&column)
    {
        getchar();

        NumHome=1;
        NumMan=1;

        for(i=1;i<=row;i++)
        {
            for(j=1;j<=column;j++)
            {
                if((ch=getchar())=='m')
                {
                    man[NumMan].row=i;
                    man[NumMan++].column=j;
                   
                   
                }
                else if(ch=='H')
                {
                    home[NumHome].row=i;
                    home[NumHome++].column=j;
                }
            }
            getchar();
        }
NumMan--;
NumHome--;
        memset(w,0,sizeof(w));
        for(i=1;i<=NumMan;i++)
            for(j=1;j<=NumHome;j++)
            {
                w[i][j]=abs(man[i].row-home[j].row)+abs(man[i].column-home[j].column);
               
            }
            memset(lx,127,sizeof(lx));
           
            memset(ly,0,sizeof(ly));
            for(i=1;i<=NumMan;i++)
                for(j=1;j<=NumHome;j++)
                {
                    if(w[i][j]<lx[i])
                    {
                        lx[i]=w[i][j];//如果是最大权匹配,则取最大值
                    }
                }
                memset(matchy,0,sizeof(matchy));
                for(i=1;i<=NumMan;i++)
                {
                    while(1)
                    {
                        memset(visitx,0,sizeof(visitx));
                        memset(visity,0,sizeof(visity));
                       
                       
                        //memset(&min,127,sizeof(min));
                        min=10000000;
                        if(dfs(i))
                            break;
                        for(j=1;j<=NumMan;j++)
                        {
                            if(visitx[j])
                            {
                                for(k=1;k<=NumHome;k++)
                                {
                                    if(visity[k]==false&&((w[j][k]-ly[k]-lx[j])<min))//lx[i]+ly[j]>=w[i,j](最大权), lx[i]+ly[j]<=W[i](最小权)
                                    {
                                    min=w[j][k]-ly[k]-lx[j];
                                    }
                                }
                            }
                        }
                        for(k=1;k<=NumMan;k++)
                        {
                            if(visitx[k])
                            {
                                lx[k]+=min;
                            }
                        }
                        for(k=1;k<=NumHome;k++)
                        {
                            if(visity[k])
                            {
                                ly[k]-=min;
                            }
                        }
                    }
                   
                }
                total=0;
                for(i=1;i<=NumHome;i++)
                {
                    total+=w[matchy[i]][i];
                }
                printf("%d/n",total);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值