poj 2195 Going Home(最小费最大流)
poj 2195 Going Home
Description
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的含有“H”, “m”。 “.”的二维图。“H”代表HOME。 “m”代表man,“.”代表空。man到HOME的距离为两点坐标的X坐标之差的绝对值加上Y坐标之差的绝对值。man的数量与HOME的数量同样。
如今。问,要是全部的man都回到HOME走的最短的路程总和为多少。
解题思路:还是建图的问题。依据这张二位的图,建一张流图。设置一个超级源点,连向全部的man,容量为1。设置一个超级汇点。使全部的HOME都连向超级汇点,容量为1。
把全部的HOME都拆成两个点。连接的容量为1。每一个房子仅仅能住一个人。
每一个man连向全部的房子,容量为1。费用为二维图上,man点到HOME点的距离。图建完以后。求最小费最大流。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
using namespace std;
const int N = 505;
const int NN = 105;
const int MM = 15005;
const int INF = 0x3f3f3f3f;
const int OF = 100;
const int FIN = 500;
typedef long long ll;
int n, m, cntH, cntM, s, t;
struct Node{
int x, y;
}H[NN], M[NN];
char gra[NN][NN];
int pre[N], inq[N];
ll a[N], d[N];
struct Edge{
int from, to;
ll cap, flow;
ll cos;
};
vector<Edge> edges;
vector<int> G[MM];
void init() {
for (int i = 0; i < MM; i++) G[i].clear();
edges.clear();
}
void addEdge(int from, int to, ll cap, ll flow, ll cos) {
edges.push_back((Edge){from, to, cap, 0, cos});
edges.push_back((Edge){to, from, 0, 0, -cos});
int m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
int getDis(int x, int y) {
return abs(M[x].x - H[y].x) + abs(M[x].y - H[y].y);
}
void input() {
cntH = cntM = 0;
for (int i = 0; i < n; i++) scanf("%s", gra[i]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (gra[i][j] == 'H') {
H[cntH].x = i;
H[cntH++].y = j;
} else if (gra[i][j] == 'm') {
M[cntM].x = i;
M[cntM++].y = j;
}
}
}
for (int i = 1; i <= cntH; i++) {
addEdge(i, i + OF, 1, 0, 0);
}
for (int i = 1; i <= cntM; i++) {
for (int j = 1; j <= cntH; j++) {
addEdge(i + 2 * OF, j, 1, 0, getDis(i - 1, j - 1));
}
}
for (int i = 1; i <= cntM; i++) {
addEdge(0, i + 2 * OF, 1, 0, 0);
}
for (int i = 1; i <= cntH; i++) {
addEdge(i + OF, t, 1, 0, 0);
}
}
int BF(int s, int t, ll& flow, ll& cost) {
queue<int> Q;
memset(inq, 0, sizeof(inq));
memset(a, 0, sizeof(a));
memset(pre, 0, sizeof(pre));
for (int i = 0; i < N; i++) d[i] = INF;
d[s] = 0;
a[s] = INF;
inq[s] = 1;
int flag = 1;
pre[s] = 0;
Q.push(s);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = 0;
for (int i = 0; i < G[u].size(); i++) {
Edge &e = edges[G[u][i]];
if (e.cap > e.flow && d[e.to] > d[u] + e.cos) {
d[e.to] = d[u] + e.cos;
a[e.to] = min(a[u], e.cap - e.flow);
pre[e.to] = G[u][i];
if (!inq[e.to]) {
inq[e.to] = 1;
Q.push(e.to);
}
}
}
flag = 0;
}
if (d[t] == INF) return 0;
flow += a[t];
cost += (ll)d[t] * (ll)a[t];
for (int u = t; u != s; u = edges[pre[u]].from) {
edges[pre[u]].flow += a[t];
edges[pre[u]^1].flow -= a[t];
}
return 1;
}
int MCMF(int s, int t, ll& cost) {
ll flow = 0;
cost = 0;
while (BF(s, t, flow, cost));
return flow;
}
int main() {
while (scanf("%d %d\n", &n, &m) == 2, n, m) {
s = 0, t = FIN;
init();
input();
ll cost;
MCMF(s, t, cost);
printf("%lld\n", cost);
}
return 0;
}
poj 2195 Going Home(最小费最大流)的更多相关文章
- POJ 2195 Going Home 最小费用最大流 尼玛,心累
D - Going Home Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Subm ...
- POJ 2195 - Going Home - [最小费用最大流][MCMF模板]
题目链接:http://poj.org/problem?id=2195 Time Limit: 1000MS Memory Limit: 65536K Description On a grid ma ...
- poj 2195 Going Home(最小费用最大流)
题目:http://poj.org/problem?id=2195 有若干个人和若干个房子在一个给定网格中,每人走一个都要一定花费,每个房子只能容纳一人,现要求让所有人进入房子,且总花费最小. 构造一 ...
- poj 2135 Farm Tour 最小费最大流
inf开太小错了好久--下次还是要用0x7fffffff #include<stdio.h> #include<string.h> #include<vector> ...
- poj 2195 二分图带权匹配+最小费用最大流
题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...
- POJ 2195 Going Home / HDU 1533(最小费用最大流模板)
题目大意: 有一个最大是100 * 100 的网格图,上面有 s 个 房子和人,人每移动一个格子花费1的代价,求最小代价让所有的人都进入一个房子.每个房子只能进入一个人. 算法讨论: 注意是KM 和 ...
- 【POJ 2195】 Going Home(KM算法求最小权匹配)
[POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submiss ...
- POJ 2195 Going Home (带权二分图匹配)
POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...
- POJ2195 Going Home (最小费最大流||二分图最大权匹配) 2017-02-12 12:14 131人阅读 评论(0) 收藏
Going Home Description On a grid map there are n little men and n houses. In each unit time, every l ...
随机推荐
- MYSQL 源代码学习
http://ourmysql.com/ http://blog.chinaunix.net/uid-26896862-id-4009777.html
- java二分查找法
//二分查找法.必须有前提:数组中的元素要有序. public static int halfSeach_2(int[] arr,int key){ int min,max,mid; min = ; ...
- Android之从Browser中打开本地的应用程序&微信检测是否有对应app
在对应的应用程序的AndroidManifest.xml中配置: <activity android:name=".ui.TabHostActivity" android:w ...
- Servlet监听器统计在线人数
监听器的作用是监听Web容器的有效事件,它由Servlet容器管理,利用Listener接口监听某个执行程序,并根据该程序的需求做出适应的响应. 例1 应用Servlet监听器统计在线人数. (1)创 ...
- C++类模板的声明和定义为什么要放在同一个文件
不是只能放在.h里面,但是推荐放在.h里面.STL模板实现全部是放在.h里面的.------------------编译能通过.1)参与编译的只是.cpp文件,不会报错的原因,是因为它能在.h里面找到 ...
- Data Binding MVVM 数据绑定 总结
示例代码:https://github.com/baiqiantao/DataBindingTest 参考:精通Android Data Binding Android Data Binding ...
- Decorator Wrapper 装饰模式 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 值得收藏的十二条Jquery随身笔记
1.关于页面元素的引用 通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用do ...
- CSS 的优先级机制总结
一.样式优先级: 多重样式(Multiple Styles):如果外部样式.内部样式和内联样式同时应用于同一个元素,就是使用多重样式的情况. 一般情况下,大家都认为优先级是:内联样式 > 内部样 ...
- 【Docker】基于docker+etcd+confd + haproxy构建高可用、自发现的web服务
各个工具介绍 (1)Docker:Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux机器上,也可以实现虚拟化,docker ...