HDU 1533:Going Home(KM算法求二分图最小权匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=1533
Going Home
Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point. 
You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0
Sample Output
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 105
#define INF 0x3f3f3f
char maze[N][N];
int mp[N][N],match[N],lx[N],ly[N],visx[N],visy[N],slack[N];
int n,m,cnt;
struct node
{
int a,b;
}sa[N],sb[N];
//KM求二分图最小匹配模板:只需把权值都变成负的,再用KM算出最大权匹配,然后取反就是答案
//学习KM地址:http://blog.sina.com.cn/s/blog_691ce2b701016reh.html
bool dfs(int x)
{
visx[x]=;
for(int y=;y<=cnt;y++){
if(visy[y]) continue;
int t=lx[x]+ly[y]-mp[x][y];
if(t==){
visy[y]=;
if(match[y]==-||dfs(match[y])){
match[y]=x;
return true;
}
}
else if(slack[y]>t) slack[y]=t;
}
return false;
} int KM()
{
memset(match,-,sizeof(match));
memset(lx,-INF,sizeof(lx));
memset(ly,,sizeof(ly));
for(int i=;i<=cnt;i++){
for(int j=;j<=cnt;j++){
if(mp[i][j]>lx[i]) lx[i]=mp[i][j];
}
}
for(int i=;i<=cnt;i++){
for(int y=;y<=cnt;y++)
slack[y]=INF;
while(){
memset(visx,,sizeof(visx));
memset(visy,,sizeof(visy));
if(dfs(i)) break;
int d=INF;
for(int y=;y<=cnt;y++){
if(!visy[y]&&d>slack[y]) d=slack[y];
}
for(int x=;x<=cnt;x++){
if(visx[x]) lx[x]-=d;
}
for(int y=;y<=cnt;y++){
if(visy[y]) ly[y]+=d;
else slack[y]-=d;
}
}
}
int res=;
for(int i=;i<=cnt;i++){
if(match[i]>-) res+=mp[match[i]][i];
}
return res;
} int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)){
if(n+m==) break;
for(int i=;i<=n;i++){
scanf("%s",maze[i]+);
}
int cnt1=,cnt2=;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(maze[i][j]=='m'){
sa[++cnt1].a=i;
sa[cnt1].b=j;
}
if(maze[i][j]=='H'){
sb[++cnt2].a=i;
sb[cnt2].b=j;
}
}
}
cnt=cnt1;
for(int i=;i<=cnt1;i++){
for(int j=;j<=cnt2;j++){
mp[i][j]=abs(sa[i].a-sb[j].a)+abs(sa[i].b-sb[j].b);
mp[i][j]=-mp[i][j];
}
}
printf("%d\n",-KM());
}
return ;
}
HDU 1533:Going Home(KM算法求二分图最小权匹配)的更多相关文章
- [ACM] HDU 1533 Going Home (二分图最小权匹配,KM算法)
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...
- [ACM] POJ 3686 The Windy's (二分图最小权匹配,KM算法,特殊建图)
The Windy's Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4158 Accepted: 1777 Descr ...
- HDU 1533 二分图最小权匹配 Going Home
带权二分图匹配,把距离当做权值,因为是最小匹配,所以把距离的相反数当做权值求最大匹配. 最后再把答案取一下反即可. #include <iostream> #include <cst ...
- POJ 2195 Going Home 【二分图最小权值匹配】
传送门:http://poj.org/problem?id=2195 Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submis ...
- UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design
题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi ...
- KM算法(二分图的最佳完美匹配)
KM算法大概过程: (1)初始化Lx数组为该boy的一条权值最大的出边.初始化Ly数组为 0. (2)对于每个boy,用DFS为其找到一个girl对象,顺路记录下S和T集,并更新每个girl的slac ...
- poj 3565 uva 1411 Ants KM算法求最小权
由于涉及到实数,一定,一定不能直接等于,一定,一定加一个误差<0.00001,坑死了…… 有两种事物,不难想到用二分图.这里涉及到一个有趣的问题,这个二分图的完美匹配的最小权值和就是答案.为啥呢 ...
- 【POJ 2195】 Going Home(KM算法求最小权匹配)
[POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submiss ...
- poj3565 Ants km算法求最小权完美匹配,浮点权值
/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...
随机推荐
- 汉顺平html5课程分享:6小时制作经典的坦克大战!
记起自己去年參加的一次面试,在做过Java多年的面试官面前发挥的并不好,但他一听说我会html5,立刻眼睛发亮.无论不顾的想要和我签约.. .所以.如今为工作犯愁的朋友们,学好html5,绝对会为你找 ...
- WPF: WrapPanel 容器的数据绑定(动态生成控件、遍历)
原文:WPF: WrapPanel 容器的数据绑定(动态生成控件.遍历) 问题: 有一些CheckBox需要作为选项添加到页面上,但是数目不定.而为了方便排版,我选择用WrapPanel ...
- WPF 中style文件的引用
原文:WPF 中style文件的引用 总结一下WPF中Style样式的引用方法: 一,内联样式: 直接设置控件的Height.Width.Foreground.HorizontalAlignment. ...
- win10 uwp 如何判断一个对象被移除
原文:win10 uwp 如何判断一个对象被移除 有时候需要知道某个元素是否已经被移除,在优化内存的时候,有时候无法判断一个元素是否在某个地方被引用,就需要判断对象设置空时是否被回收. 本文告诉大家一 ...
- Python杂谈: 集合中union和update的区别(Python3.x)
集合中union和update方法都是将多个可迭代的对象合并,但是返回的结果和对初始对象的影响却不一样 # union() 方法 - a.union(b) 将集合a和集合b取并集,并将并集作为一个新的 ...
- Delphi中流对象的应用
Delphi的流对象(TStream的派生对象)有如下读写函数: function Read(var Buffer; Count: Longint): Longint;function Write(c ...
- Android CTS Test failed to run to conmpletion 测试超时问题
引用“Android cts all pass 全攻略”里面的一段话: ❀ testcase timeout 测试某个testcase的时候一直出现 “........”,迟迟没有pass或者fail ...
- Decision Tree
Decision Tree builds classification or regression models in the form of a tree structure. It break d ...
- CWnd和HWND的区别(hWnd只是CWnd对象的一个成员变量,代表与这个对象绑定的窗口)
所有控件类都是CWnd类的派生类,CWnd的所有成员函数在控件类中都可以使用.在MFC中,CWnd类是一个很重要的类,它封装了Windows的窗口句柄HWND.在Windows编程中, ...
- mqtt消息推送
https://github.com/wizinfantry/delphi-mqtt-clienthttps://github.com/Indemsys/Delphi_MQTT_mosquittoht ...