[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 ...
随机推荐
- 安装glibc错误链接导致系统崩溃,u盘启动紧急救援模式下修复系统。
Sln 命令 创建动态符号链接 用法 sln source dest 故障案例:一个误操作 导致了一个不小的故障,输入所有命令都无效,直接系统无法启动. 故障描述 sln /usr/lib64/l ...
- LeetCode OJ--Combination Sum **
https://oj.leetcode.com/problems/combination-sum/ 给一列数,3 2 1 3 3 8 7 9 ,每个数可以重复多次,给target 7, 问可以加起来得 ...
- AC日记——[国家集训队2010]小Z的袜子 cogs 1775
[国家集训队2010]小Z的袜子 思路: 传说中的莫队算法(优雅的暴力): 莫队算法是一个离线的区间询问算法: 如果我们知道[l,r], 那么,我们就能O(1)的时间求出(l-1,r),(l+1,r) ...
- Codeforces 754A(搜索)
设s[i][j]为序列i到j的和,当s[i][j]≠0时,即可从i跳到j+1.目标为从1跳到n+1,所以按照题意暴力即可. #include <bits/stdc++.h> using n ...
- 在Linux 双机下自己手动实现浮动ip技术
两台Linux服务器,一台为主机(IP:124.158.26.30)对外提供了一定的网络服务,另一台从机(IP:124.158.26.31)能提供相同的服务,但ip地址没有对外部公开客户端连接的都是1 ...
- noip2017集训测试赛(四)Problem A: fibonacci
题目大意 给你一个序列\(a_1, a_2, ..., a_n\). 我们令函数\(f(n)\)表示斐波那契数列第\(n\)项的值. 总共\(m\)个操作, 分为以下两种: 将\(x \in [L, ...
- Mysql乱码问题解决历程
可能是因为看了太多网上的关于这个问题的解决办法,可能当时是我自己没有看明白也或许是情况不一样,反正都没有解决我当初遇到的问题,现在想想可能是自己当初太无知了,第二个原因是原来大多数情况下是在windo ...
- Scut游戏服务器引擎6.0.5.1发布
1. 修正缓存删除时不会更新到Redis的问题 2. 修正Model组合3个以上子类时Change事件未绑定的问题 3. 修正中间层MySql与MsSql数据库Sql语句分页问题
- ci框架文件上传
控制器类代码 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Upload ex ...
- getchar()和getch()的区别
1.getchar();从键盘读取一个字符并输出,该函数的返回值是输入第一个字符的ASCII码:若用户输入的是一连串字符,函数直到用户输入回车时结束,输入的字符连同回车一起存入键盘缓冲区.若程序中有后 ...