【POJ 2195】 Going Home(KM算法求最小权匹配)
【POJ 2195】 Going Home(KM算法求最小权匹配)
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 20303 | Accepted: 10297 |
Description
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.

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.
Input
the 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.
Output
Sample Input
2 2
.m
H.
5 5
HH..m
.....
.....
.....
mm..H
7 8
...H....
...H....
...H....
mmmHmmmm
...H....
...H....
...H....
0 0
Sample Output
2
10
28
Source
越来越认为KM算法是种非常奇妙的算法,或者说各种图论算法都好奇妙……在或者说 图是一种奇妙的东西。。。一个题可能有多种算法能够解决
这题之前一仅仅用最小费做的,一直以为是唯一的做法。
今天做KM突然发现 这题之前不是做过么……
这题用KM算法会快非常多。并且代码量少一点。
只是思想的算法。没法做什么比較。
题目大意就是一定数量的人和房子。保证人和房子数量同样,要求分配每一个人到相应的房子里,而且人与房子一一相应。问全部人须要移动的最少步数。建图我是把人和房子的坐标用pair存成数组,然后求出每一个人到每一个房子的距离。也就是最初的二分图。
之后用KM求最小权,跟最大权一种套路,仅仅只是建图的时候权值取负,这样求出的最大权事实上绝对值是最小的。换句话说取反回来后,事实上就是所求的解。
代码例如以下:
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout)
#define Pr pair<int,int> using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const double eps = 1e-8; //二分图
int mp[233][233];
// x顶标 y顶标
int lx[233],ly[233],link[233],slick[233];
bool visx[233],visy[233];
// 人的坐标 房子坐标
Pr human[233],house[233];
//人数 房数
int nm,nh; bool cal(int x)
{
visx[x] = 1;
for(int y = 0; y < nh; ++y)
{
if(visy[y]) continue; int t = lx[x]+ly[y]-mp[x][y];
if(t == 0)
{
visy[y] = 1;
if(link[y] == -1 || cal(link[y]))
{
link[y] = x;
return true;
}
}
else slick[y] = min(slick[y],t);
}
return false;
} int KM()
{
memset(link,-1,sizeof(link)); for(int i = 0; i < nm; ++i)
{
memset(slick,INF,sizeof(slick));
while(1)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
if(cal(i)) break;
int d = INF; for(int j = 0; j < nh; ++j)
if(!visy[j]) d = min(d,slick[j]); for(int j = 0; j < nm; ++j)
if(visx[j]) lx[j] -= d; for(int j = 0; j < nh; ++j)
if(visy[j]) ly[j] += d;
else slick[j] -= d;
}
} int ans = 0;
for(int i = 0; i < nh; ++i)
if(link[i] != -1) ans += mp[link[i]][i]; return ans;
} int main()
{
int n,m;
char tmp[233]; while(~scanf("%d%d",&n,&m) && (n+m))
{
nm = nh = 0;
for(int i = 0; i < n; ++i)
{
scanf("%s",tmp);
for(int j = 0; j < m; ++j)
if(tmp[j] == 'm') human[nm++] = Pr(i,j);
else if(tmp[j] == 'H') house[nh++] = Pr(i,j);
} memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly)); for(int i = 0; i < nm; ++i)
for(int j = 0; j < nh; ++j)
{
mp[i][j] = -(abs(human[i].first-house[j].first)+abs(human[i].second-house[j].second));
lx[i] = max(lx[i],mp[i][j]);
} printf("%d\n",-KM());
} return 0;
}
【POJ 2195】 Going Home(KM算法求最小权匹配)的更多相关文章
- poj3565 Ants km算法求最小权完美匹配,浮点权值
/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...
- poj 3565 uva 1411 Ants KM算法求最小权
由于涉及到实数,一定,一定不能直接等于,一定,一定加一个误差<0.00001,坑死了…… 有两种事物,不难想到用二分图.这里涉及到一个有趣的问题,这个二分图的完美匹配的最小权值和就是答案.为啥呢 ...
- 【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)
[POJ 2400] Supervisor, Supervisee(KM求最小权匹配) Supervisor, Supervisee Time Limit: 1000MS Memory Limit ...
- hdu1533 Going Home km算法解决最小权完美匹配
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- poj 2195(KM求最小权匹配)
题目链接:http://poj.org/problem?id=2195 思路:我们都知道KM使用来求最大权匹配的,但如果要求最小权匹配,只需把图中的权值改为负值,求一次KM,然后权值和取反即可. ht ...
- poj 2195 Going Home (km算法)
题目链接: http://poj.org/problem?id=2195 解题思路: 把man和home都提取出来,然后算出每个man和home的距离算出来,然后建立匹配图,套用km算法的模板,求最小 ...
- POJ-2195 Going Home---KM算法求最小权值匹配(存负边)
题目链接: https://vjudge.net/problem/POJ-2195 题目大意: 给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致.man每移动一格 ...
- [ACM] POJ 3686 The Windy's (二分图最小权匹配,KM算法,特殊建图)
The Windy's Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4158 Accepted: 1777 Descr ...
- Fixed Partition Memory Management UVALive - 2238 建图很巧妙 km算法左右顶点个数不等模板以及需要注意的问题 求最小权匹配
/** 题目: Fixed Partition Memory Management UVALive - 2238 链接:https://vjudge.net/problem/UVALive-2238 ...
随机推荐
- [APIO2012]派遣 可并堆(左偏树)
没啥说的,自底向上合并大根堆即可. 一边合并,一边贪心弹堆顶直到堆的总和不大于预算. Code: #include <cstdio> #include <algorithm> ...
- 路飞学城Python-Day14
转载:python之路-路飞学城-python-book [25.常用模块-logging模块详解] [26.常用模块-logging模块详解2] [27.常用模块-logging模块日志过滤和日志文 ...
- How Javascript works (Javascript工作原理) (一) 引擎,运行时,函数调用栈
个人总结:该系列文章对JS底层的工作原理进行了介绍. 这篇文章讲了 运行时:js其实是和AJAX.DOM.Settimeout等WebAPI独立分离开的 调用栈:JavaScript的堆内存管理 和 ...
- HDU 6051 If the starlight never fade(原根+推式子)
题目大意: 设\(f(i)\)为使\((x+y)^i \equiv x^i (mod\ p)\)成立的(x,y)的对数.其中\(1 \leq x \leq p-1 , 1\leq y\leq m\), ...
- C语言Huffman压缩和解压
符号表结构体: struct node { // 字符串形式存储的Huffman编码 char code[MAX_CODE_LENGTH]; // 这个字符在文件中出现的次数 long count; ...
- 【BZOJ 1005】[HNOI2008]明明的烦恼(暴力化简法)
[题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1005 [题意] 中文题 [题解] 一棵节点上标有序号的树会和一个prufer数列唯一对 ...
- C - The C Answer (2nd Edition) - Exercise 1-12
/* Write a program that prints its input one word per line. */ #include <stdio.h> #define IN 1 ...
- c++_benchMark_vector_list_deque
title: c++_benchMark_vector_list_deque date: 2015-08-01 22:32:39 作者:titer1 + ZhangYu 出处:www.drysalte ...
- jQuery -> 怎样【先创建、再改动、后加入】 DOM元素
怎样一气呵成地.on the fly地操作DOM元素呢? 比如顺序运行[创建]-> [改动]-> [加入]三个动作. 因为jQuery支持链式操作,事实上就是设计模式的builder模式, ...
- SQLSever: 怎样在select中的每一行产生不同的随机数?
select 的随机函数有点假, 或许是由于它是基于时间来的吧, 同一select中由于时间无法错开导致产生的随机数都是一样的. 怎样做到让不同的行拥有不同的随机数呢? 以下以产生某个月的随机日期来演 ...