[POJ2195]Going Home(KM)

题目:

我是超链接

题解:

转来KM啦,这是一道裸题哦
KM算法是用来求二分图最大带权匹配的,这里安利一下讲的比较好的blog,对于这道题来说只需要把边权全都设为负的求个最大值然后取反就是最小的路咯
如果你不每次清空l[x]和r[x],而是加一个编号的话,效率更好哦

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 1e9
using namespace std;
struct hh{int x,y;}ren[105],hou[105];
char st[105];
int e[105][105],lx[105],ly[105],n,belong[105],vis[205],id,toth;
bool find(int i,int id)
{
    vis[i]=id;
    for (int j=1;j<=n;j++)
      if (lx[i]+ly[j]==e[i][j] && vis[j+n]!=id)
      {
        vis[j+n]=id;
        if (!belong[j] || find(belong[j],id))
        {
            belong[j]=i;
            return 1;
        }
      }
    return 0;
}
void change(int id)
{
    int i,j,a=INF;
    for (i=1;i<=n;i++)
      if (vis[i]==id)
        for (j=1;j<=n;j++)
          if (vis[j+n]!=id) a=min(a,lx[i]+ly[j]-e[i][j]);
    for (i=1;i<=n;i++)
    {
        if (vis[i]==id) lx[i]-=a;
        if (vis[i+n]==id) ly[i]+=a;
    }
}
int KM()
{
    int i,j,ans=0;
    memset(vis,0,sizeof(vis));
    for (i=1;i<=n;i++)
    {
        belong[i]=0;lx[i]=ly[i]=0;
        for (j=1;j<=n;j++) lx[i]=max(lx[i],e[i][j]);
    }
    for (i=1;i<=n;i++)
      while(1)
      {
        ++id;
        if (find(i,id)) break;
        else change(id);
      }
    for (i=1;i<=n;i++) ans+=e[belong[i]][i];
    return ans;
}
int main()
{
    int nn,m,i,j;
    scanf("%d%d",&nn,&m);
    while (nn)
    {
        n=toth=0;
        for (i=1;i<=nn;i++)
        {
            scanf("%s",st+1);
            for (j=1;j<=m;j++)
              if (st[j]=='m') ren[++n].x=i,ren[n].y=j;
              else if (st[j]=='H') hou[++toth].x=i,hou[toth].y=j;
        }
        for (i=1;i<=n;i++)
          for (j=1;j<=toth;j++)
            e[i][j]=-(abs(ren[i].x-hou[j].x)+abs(ren[i].y-hou[j].y));
        printf("%d\n",-KM());
        scanf("%d%d",&nn,&m);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值