题干:

On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need to pay a $1 travel fee for every 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

There are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing 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

For each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay.

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

题目大意:

在n*m的矩阵格子里有x个人('m')要走到x个房间('H')里,每个房间里只能放一人,人在目前所在的格子处向上下左右相邻的格子走一步就花费1美元,问最后全部的人走到房间后最小的花费。

解题报告:

直接建图之后最小费用流。

新建超级源点st,超级汇点ed。

st连向每一个m,流量为1,费用为0。

每一个H连向ed,

新增源点from和汇点to,from->人(w为1,cost为0)

房子->to(w为1,cost为0)

每个人->每间房(w为1,cost为最短路径的美元花费)

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
using namespace std;const int MAXN = 70000;
const int MAXM = 100005;
const int INF = 0x3f3f3f3f;
struct Edge {int to,next,cap,flow,cost;
} edge[MAXM];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
int N;//节点总个数,节点编号从 1 ~ N
void init(int n) {N = n;tol = 0;memset(head, -1,sizeof(head));
}
void addedge(int u,int v,int cap,int cost) {edge[tol].to = v;edge[tol].cap = cap;edge[tol].cost = cost;edge[tol].flow = 0;edge[tol].next = head[u];head[u] = tol++;edge[tol].to = u;edge[tol].cap = 0;edge[tol].cost = -cost;edge[tol].flow = 0;edge[tol].next = head[v];head[v] = tol++;
}
bool spfa(int s,int t) {queue<int>q;for(int i = 1; i <= N; i++) {dis[i] = INF;vis[i] = false;pre[i] = -1;}dis[s] = 0;vis[s] = true;q.push(s);while(!q.empty()) {int u = q.front();q.pop();vis[u] = false;for(int i = head[u]; i !=-1; i = edge[i].next) {int v = edge[i].to;if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost ) {dis[v] = dis[u] + edge[i].cost;pre[v] = i;if(!vis[v]) {vis[v] = true;q.push(v);}}}}if(pre[t] ==-1)return false;else return true;}
//返回的是最大流,cost 存的是最小费用
int minCostMaxflow(int s,int t,int &cost) {int flow = 0;cost = 0;while(spfa(s,t)) {int Min = INF;for(int i = pre[t]; i !=-1; i = pre[edge[i^1].to]) {if(Min > edge[i].cap-edge[i].flow)Min = edge[i].cap-edge[i].flow;}for(int i = pre[t]; i !=-1; i = pre[edge[i^1].to]) {edge[i].flow += Min;edge[i^1].flow-= Min;cost += edge[i].cost * Min;}flow += Min;}return flow;
}
char s[111][111];
int r[111],c[111];
int R[111],C[111];
int tot1,tot2;
int main()
{int n,m;while(~scanf("%d%d",&n,&m)) {if(n == 0 && m == 0) break;init(n*m+2);memset(dis,0,sizeof dis);tot1=tot2=0;int st=n*m+1,ed=n*m+2;int cost;for(int i = 1; i<=n; i++) {scanf("%s",s[i]+1);}for(int i = 1; i<=n; i++) {for(int j = 1; j<=m; j++) {if(s[i][j] == 'm') tot1++,r[tot1] = i,c[tot1] = j;if(s[i][j] == 'H') tot2++,R[tot2] = i,C[tot2] = j;}}for(int i = 1; i<=tot1; i++) {for(int j = 1; j<=tot2; j++) addedge(i,tot1+j,1,abs(c[i]-C[j]) + abs(r[i]-R[j]));}for(int i = 1; i<=tot1; i++) addedge(st,i,1,0);for(int i = 1; i<=tot2; i++) addedge(tot1+i,ed,1,0);int ans = minCostMaxflow(st,ed,cost);printf("%d\n",cost);}    return 0 ;
}

【HDU - 1533】Going Home(网络流,二分图最优匹配,KM算法)相关推荐

  1. 二分图最佳完美匹配——KM算法总结

    KM 算法 求解二分图最佳完美匹配的算法. 先来看一道例题Hdu 2255. 显然是KM的裸题.假设我们要匹配集合X和Y的点,先给每个点一个顶标Lx和Ly. 为什么要给顶标? 首先顶标是我们限制边的一 ...

  2. 二分图最大权匹配 KM算法

    KM算法的正确性基于以下定理: 若由二分图中所有满足A[i]+B[i]=w[i][j]的边C(i,j)构成的子图(即相等子图)有完备匹配,那么这个完备匹配就是二分图的最大权匹配 基本概念 1.完备匹配 ...

  3. 二分图的完全匹配---KM算法

    写在之前:更多二分图知识,请关注--->二分图知识导航篇 引述 KM算法全称Kuhn-Munkres,是一种求二分图完全.完美.最佳等匹配的方法,其实三个形容词都是指两个集内的所有顶点能够一一匹 ...

  4. 【算法笔记】二分图最大权匹配 - KM算法(dfs版O(n4) + bfs版O(n3))

    整理的算法模板合集: ACM模板 匈牙利算法又称为 KM 算法,可以在 O(n3)O(n^3)O(n3) 时间内求出二分图的 最大权完美匹配 . 考虑到二分图中两个集合中的点并不总是相同,为了能应用 ...

  5. 二分图最佳完美匹配——KM算法

    前情概要 学km算法之前,笔者还是希望大家已经掌握了匈牙利算法--也就是对于求解二分图最大匹配的算法.学习本算法的前提除了已经掌握C++语言之外,还需要掌握邻接表存图法,不会的朋友这里有传送门 [微笑 ...

  6. HDU 1853 HDU 3488【有向环最小权值覆盖问题 】带权二分图匹配 KM算法

    HDU 1853 & HDU 3488[有向环最小权值覆盖问题 ]最小费用最大流 In the kingdom of Henryy, there are N (2 <= N <= ...

  7. 【POJ - 2195】Going Home(二分图最优匹配,费用流 或 KM)

    题干: On a grid map there are n little men and n houses. In each unit time, every little man can move ...

  8. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  9. 训练指南 UVALive - 4043(二分图匹配 + KM算法)

    layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true ...

  10. 奔小康赚大钱 HDU - 2255( 二分图匹配KM算法详解)

    题目 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.  这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百 ...

最新文章

  1. rancher 外置 mysql_rancher使用外部数据库无法正常使用
  2. 基于HttpClient的HttpUtils(后台访问URL)
  3. python TypeError: Expected int32, got list containing Tensors of type '_Message' instead.
  4. Spring容器装饰者模式应用之实现业务类与服务类自由组合的解决方式
  5. 经典C语言程序100例之七零
  6. SAP CRM Business partner API里的buffer设计
  7. bootstrap后台模板_免费bootstrap后台管理系统模板源码 网站后台模板_后台管理界面...
  8. 模板全特化和偏特化用法
  9. 小甲鱼python课后题简书_Python练习题100道
  10. matlab multithreading spyder,spyder和python的关系是什么
  11. java文件快速扫描仪_有没有办法从Java中的方法提供自动扫描仪输入?
  12. ubuntu drbd双机互备
  13. js中数组反向、排序reverse、sort
  14. C#中virtual与abstract的区别
  15. 数学建模之常见的优化模型
  16. 视频教程-Qt语言从入门到精通-C/C++
  17. eclipse设置护眼豆沙色
  18. linux退出热键_linux用户退出登录的命令介绍
  19. Redis优化及配置
  20. [转载] 新妖女传说:奸魔

热门文章

  1. [原]2011年度生活三层总结
  2. 【原创】StreamInsight查询系列(十九)——查询模式之检测异常
  3. [Leetcode][第257题][JAVA][二叉树的所有路径][BFS][DFS]
  4. [剑指offer][JAVA]面试题第[21]题[调整数组顺序使奇数位于偶数面前][双指针]
  5. [Leedcode][JAVA][第25题][K个一组反转链表][链表][递归]
  6. mysql 命令行 主从复制_MySQL 的主从复制(高级篇)
  7. C++ function bind以及lamda表达式
  8. 群晖218 修改服务器名称,一次换群晖引发的各种事情——论如何榨干218+的价值【不完全版】...
  9. AD16原理图.schdot中批量修改标签中的文本字体、大小、颜色
  10. 怎么查看usb读取信息_电脑弹出USB设备时提示该设备正在使用中的解决方法