[ACM] HDU 1533 Going Home (二分图最小权匹配,KM算法)
Going Home
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2963 Accepted Submission(s): 1492
step he moves, until he enters a house. The task is complicated with the restriction that each house can accommodate only one little man.
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.
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc3JfMTk5MzA4Mjk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
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.
map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of 'H's and 'm's on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.
2 2
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0
2
10
28
解题思路:
题意为n*m的方格中有p个房子和p个人,人每走一步花费1美元,要求每一个人都要找到一个房子,且每一个房子里仅仅能有一个人,问p个人都找到各自的房子。最小的花费是多少。
能够用KM算法求出最大的花费,要求最小花费仅仅要把邻接矩阵中的权值取反。然后用Km算法最后返回 最大值的相反数就是要求的最小花费。
代码:
#include <iostream>
#include <string.h>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=102;
const int inf=0x3f3f3f3f;
char mp[maxn][maxn];
int n,m;
int npeople;
int g[maxn][maxn];
int nx,ny;
int linked[maxn],lx[maxn],ly[maxn];
int slack[maxn];
bool visx[maxn],visy[maxn]; struct House//存放房子的坐标
{
int x,y;
}house[maxn]; struct Man//存放人的坐标
{
int x,y;
}man[maxn]; bool DFS(int x)//hungary
{
visx[x]=true;
for(int y=0;y<ny;y++)
{
if(visy[y])
continue;
int tmp=lx[x]+ly[y]-g[x][y];
if(tmp==0)
{
visy[y]=true;
if(linked[y]==-1||DFS(linked[y]))
{
linked[y]=x;
return true;
}
}
else if(slack[y]>tmp)
slack[y]=tmp;
}
return false;
} int KM()
{
memset(linked,-1,sizeof(linked));
memset(ly,0,sizeof(ly));
for(int i=0;i<nx;i++)
{
lx[i]=-inf;
for(int j=0;j<ny;j++)
if(g[i][j]>lx[i])
lx[i]=g[i][j];
}
for(int x=0;x<nx;x++)
{
for(int i=0;i<ny;i++)
slack[i]=inf;
while(true)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
if(DFS(x))
break;
int d=inf;
for(int i=0;i<ny;i++)
if(!visy[i]&&d>slack[i])
d=slack[i];
for(int i=0;i<nx;i++)
if(visx[i])
lx[i]-=d;
for(int i=0;i<ny;i++)
{
if(visy[i])
ly[i]+=d;
else
slack[i]-=d;
}
}
}
int ans=0;
for(int i=0;i<ny;i++)
if(linked[i]!=-1)
ans+=g[linked[i]][i];
return -ans;//返回最大的相反数。即要求的最小
} int main()
{
while(cin>>n>>m&&(n||m))
{
int h1=-1,m1=-1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>mp[i][j];
if(mp[i][j]=='H')
house[++h1].x=i,house[h1].y=j;
else if(mp[i][j]=='m')
man[++m1].x=i,man[m1].y=j;
}
npeople=(++h1);
memset(g,inf,sizeof(g));
for(int i=0;i<npeople;i++)//计算邻接矩阵
for(int j=0;j<npeople;j++)
{
int dist=abs(man[i].x-house[j].x)+abs(man[i].y-house[j].y);
g[i][j]=-dist;//权值取反
}
nx=ny=npeople;
cout<<KM()<<endl;
}
return 0;
}
[ACM] HDU 1533 Going Home (二分图最小权匹配,KM算法)的更多相关文章
- 二分图带权匹配 KM算法与费用流模型建立
[二分图带权匹配与最佳匹配] 什么是二分图的带权匹配?二分图的带权匹配就是求出一个匹配集合,使得集合中边的权值之和最大或最小.而二分图的最佳匹配则一定为完备匹配,在此基础上,才要求匹配的边权值之和最大 ...
- 二分图最大权匹配——KM算法
前言 这东西虽然我早就学过了,但是最近才发现我以前学的是假的,心中感慨万千(雾),故作此篇. 简介 带权二分图:每条边都有权值的二分图 最大权匹配:使所选边权和最大的匹配 KM算法,全称Kuhn-Mu ...
- HDU 1533:Going Home(KM算法求二分图最小权匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=1533 Going Home Problem Description On a grid map there ...
- [ACM] POJ 3686 The Windy's (二分图最小权匹配,KM算法,特殊建图)
The Windy's Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4158 Accepted: 1777 Descr ...
- 二分图 最大权匹配 km算法
这个算法的本质还是不断的找增广路: KM算法的正确性基于以下定理:若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最 ...
- HDU2255 奔小康赚大钱 —— 二分图最大权匹配 KM算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) ...
- hdu 2426 Interesting Housing Problem 最大权匹配KM算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2426 For any school, it is hard to find a feasible ac ...
- POJ3565带权匹配——km算法
题目:http://poj.org/problem?id=3565 神奇结论:当总边权最小时,任意两条边不相交! 转化为求二分图带权最小匹配. 可以用费用流做.但这里学一下km算法. https:// ...
- HDU3488 Tour —— 二分图最大权匹配 KM算法
题目链接:https://vjudge.net/problem/HDU-3488 Tour Time Limit: 3000/1000 MS (Java/Others) Memory Limit ...
随机推荐
- [SaltStack] salt-minion启动流程
SaltStack源码阅读 前面理了下salt-master的启动流程, 这次来看看salt-minion的启动流程. 启动salt-minion方法: /etc/init.d/salt-minion ...
- DOM-window下的常用子对象-location-刷新页面
1.刷新当前页面:(通过给location.href赋值的方式) window.location.href="" eg:window.location.href="htt ...
- ASP.NET MVC 利用Razor引擎生成静态页
实现原理及步骤: 1.通过ViewEngines.Engines.FindView查找到对应的视图,如果是部分视图,则用:ViewEngines.Engines.FindPartialView: 2. ...
- Linux中查看某个软件的安装路径
Linux中查看某个软件的安装路径(地址)有时显得非常重要.比如某个文件的快速启动项被删除,或者你要建立快速启动项,或者想删除.添加安装文件等等,很多地方都要用到查案文件安装路径的命令. 这里给大家介 ...
- IOS7开发~UIKit Dynamics
UIKit Dynamics的中文名称:有叫UIKit动力,也有叫UIKit动力模型和UIKit动态或者动态UI,叫什么名不要紧,理解就含义就可以了. 什么是UIKit Dynamics ? UIKi ...
- Oracle 检查表空间使用情况
--检查表空间使用情况 SELECT f.tablespace_name , a.total "total (M)" , f.free "fre ...
- 别名alias——快捷方式
有时候在 linux 或者 windows 上面需要对相关的命令进行快捷处理,这时候可以用到别名—— alias : linux别名设置假设我们需要设置一个 dockers 命令,用来替代 doc ...
- GestureDetector 完全解析
个人原创 OnDown(MotionEvent e):用户触发DonenEvent就会执行onShowPress(MotionEvent e):用户触发DonenEvent后,在很短大概0.5秒内,没 ...
- vue 父子通信过程
1.概述 每个 Vue 实例都实现了事件接口,即: 使用 $on(eventName) 监听事件 使用 $emit(eventName, optionalPayload) 触发事件 2.示例一(未传递 ...
- Centos7 安装 Maven 3.5.*
下载 Apache Maven 访问 Maven官方网站,打开后找到下载链接,如下: 解压 tar zxvf apache-maven-3.5.3-bin.tar.gz 添加环境变量 打开 /etc/ ...