题目链接:https://vjudge.net/problem/POJ-2195

Going Home
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 24015   Accepted: 12054

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

Source

题意:

给出一张n*m的图,其中里面有数量相等的人和房屋。下雨了,要为每个人安排一座房屋,且每个房屋只能容纳一个人。问:怎样安排,才能使得总的路程最短(不用考虑房屋与人的阻碍问题,即两点距离直接是曼哈顿距离)?

题解:

最大权匹配的裸题,把权值取反即可。或者用最小费用最大流去做也可以。

最大权匹配:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int MAXN = 1e2+; int nx, ny;
int g[MAXN][MAXN];
int linker[MAXN], lx[MAXN], ly[MAXN];
int slack[MAXN];
bool visx[MAXN], visy[MAXN]; bool DFS(int x)
{
visx[x] = true;
for(int y = ; y<=ny; y++)
{
if(visy[y]) continue;
int tmp = lx[x] + ly[y] - g[x][y];
if(tmp==)
{
visy[y] = true;
if(linker[y]==- || DFS(linker[y]))
{
linker[y] = x;
return true;
}
}
else
slack[y] = min(slack[y], tmp);
}
return false;
} int KM()
{
memset(linker, -, sizeof(linker));
memset(ly, , sizeof(ly));
for(int i = ; i<=nx; i++)
{
lx[i] = -INF;
for(int j = ; j<=ny; j++)
lx[i] = max(lx[i], g[i][j]);
} for(int x = ; x<=nx; x++)
{
for(int i = ; i<=ny; i++)
slack[i] = INF;
while(true)
{
memset(visx, , sizeof(visx));
memset(visy, , sizeof(visy)); if(DFS(x)) break;
int d = INF;
for(int i = ; i<=ny; i++)
if(!visy[i])
d = min(d, slack[i]); for(int i = ; i<=nx; i++)
if(visx[i])
lx[i] -= d;
for(int i = ; i<=ny; i++)
{
if(visy[i]) ly[i] += d;
else slack[i] -= d;
}
}
} int res = ;
for(int i = ; i<=ny; i++)
if(linker[i]!=-)
res += g[linker[i]][i];
return res;
} int house[MAXN][], man[MAXN][];
int main()
{
int n, m;
char str[MAXN];
while(scanf("%d%d",&n,&m)&&(m||n))
{
nx = , ny = ;
for(int i = ; i<=n; i++)
{
scanf("%s", str+);
for(int j = ; j<=m; j++)
{
if(str[j]=='H') house[++nx][] = i, house[nx][] = j;
else if(str[j]=='m') man[++ny][] = i, man[ny][] = j;
}
} memset(g, , sizeof(g));
for(int i = ; i<=nx; i++)
for(int j = ; j<=ny; j++)
g[i][j] = -(abs(house[i][]-man[j][])+abs(house[i][]-man[j][])); int ans = -KM();
printf("%d\n", ans);
}
}

最小费用最大流:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int MAXN = 1e3+; struct Edge
{
int to, next, cap, flow, cost;
}edge[<<];
int tot, head[MAXN];
int pre[MAXN], dis[MAXN];
bool vis[MAXN];
int N; void init(int n)
{
N = n;
tot = ;
memset(head, -, sizeof(head));
} void add(int u, int v, int cap, int cost)
{
edge[tot].to = v; edge[tot].cap = cap; edge[tot].cost = cost;
edge[tot].flow = ; edge[tot].next = head[u]; head[u] = tot++; edge[tot].to = u; edge[tot].cap = ; edge[tot].cost = -cost;
edge[tot].flow = ; edge[tot].next = head[v]; head[v] = tot++;
} bool spfa(int s, int t)
{
queue<int>q;
for(int i = ; i<N; i++)
{
dis[i] = INF;
vis[i] = false;
pre[i] = -;
} dis[s] = ;
vis[s] = true;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u] = false;
for(int i = head[u]; i!=-; 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]==-) return false;
return true;
} int minCostMaxFlow(int s, int t, int &cost)
{
int flow = ;
cost = ;
while(spfa(s,t))
{
int Min = INF;
for(int i = pre[t]; i!=-; i = pre[edge[i^].to])
{
if(Min>edge[i].cap-edge[i].flow)
Min = edge[i].cap-edge[i].flow;
}
for(int i = pre[t]; i!=-; i = pre[edge[i^].to])
{
edge[i].flow += Min;
edge[i^].flow -= Min;
cost += edge[i].cost*Min;
}
flow += Min;
}
return flow;
} int house[MAXN][], man[MAXN][];
int main()
{
int n, m;
char str[MAXN];
while(scanf("%d%d",&n,&m)&&(m||n))
{
int nx = , ny = ;
for(int i = ; i<=n; i++)
{
scanf("%s", str+);
for(int j = ; j<=m; j++)
{
if(str[j]=='H') house[++nx][] = i, house[nx][] = j;
else if(str[j]=='m') man[++ny][] = i, man[ny][] = j;
}
} init(nx+ny+);
for(int i = ; i<=nx; i++)
for(int j = ; j<=ny; j++)
add(i,nx+j,,abs(house[i][]-man[j][])+abs(house[i][]-man[j][])); for(int i = ; i<=nx; i++) add(,i,,);
for(int i = ; i<=ny; i++) add(nx+i,nx+ny+,,); int mincost;
minCostMaxFlow(, nx+ny+, mincost);
printf("%d\n", mincost);
}
}

POJ2195 Going Home —— 最大权匹配 or 最小费用最大流的更多相关文章

  1. poj 2195 二分图最优匹配 或 最小费用最大流

    就是最基本的二分图最优匹配,将每个人向每个房子建一条边,权值就是他们manhattan距离.然后对所有权值取反,求一次最大二分图最优匹配,在将结果取反就行了. #include<iostream ...

  2. [hdu1533]二分图最大权匹配 || 最小费用最大流

    题意:给一个n*m的地图,'m'表示人,'H'表示房子,求所有人都回到房子所走的距离之和的最小值(距离为曼哈顿距离). 思路:比较明显的二分图最大权匹配模型,将每个人向房子连一条边,边权为曼哈顿距离的 ...

  3. poj 2195 二分图带权匹配+最小费用最大流

    题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...

  4. hdu 1853 Cyclic Tour (二分匹配KM最小权值 或 最小费用最大流)

    Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others)Total ...

  5. 经典网络流题目模板(P3376 + P2756 + P3381 : 最大流 + 二分图匹配 + 最小费用最大流)

    题目来源 P3376 [模板]网络最大流 P2756 飞行员配对方案问题 P3381 [模板]最小费用最大流 最大流 最大流问题是网络流的经典类型之一,用处广泛,个人认为网络流问题最具特点的操作就是建 ...

  6. POJ2195:Going Home (最小费用最大流)

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 26212   Accepted: 13136 题目链接 ...

  7. HDU - 6437 Problem L.Videos 2018 Multi-University Training Contest 10 (最小费用最大流)

    题意:M个影片,其属性有开始时间S,结束时间T,类型op和权值val.有K个人,每个人可以看若干个时间不相交的影片,其获得的收益是这个影片的权值val,但如果观看的影片相邻为相同的属性,那么收益要减少 ...

  8. 最小费用最大流——ZKW

    对于最小费用最大流,我们的通常做法是EK+SPFA. 然而,卡常界大佬ZKW发明了一个求解最小费用最大流的方法,很强啊. 在学ZKW费用流前,先说说KM算法. KM算法 为啥要先提这个呢?因为ZKW费 ...

  9. POJ 2195:Going Home(最小费用最大流)

    http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大 ...

随机推荐

  1. Java线程池快速学习教程

    1. Java线程池 线程池:顾名思义,用一个池子装载多个线程,使用池子去管理多个线程. 问题来源:应用大量通过new Thread()方法创建执行时间短的线程,较大的消耗系统资源并且系统的响应速度变 ...

  2. mysql报错Packet for query is too large (12238 > 1024). You can change this value

    今天将项目部署到linux服务器的时候莫名其妙的报一些错误,可是在本地啥错没有,通过实时查看tomcat 的日志之后发现报错是: 实时查看日志: .先切换到:cd usr/local/tomcat5/ ...

  3. float类型的使用

    将身高字段设置为float类型,保留一位小数: ALTER TABLE `user` CHANGE `height` `height` FLOAT(4,1) UNSIGNED NOT NULL DEF ...

  4. Powerdesigner 使用小技巧

    1.table与table之间:改直角为直线; 2.Name 和code 不联动

  5. CKeditor如何实现图片上传功能

    http://makaiyuan.blog.51cto.com/5819595/1049521 如何在数据库中导入excel文件内的数据:http://jingyan.baidu.com/album/ ...

  6. css,世界上没有绝对简单的事情

    引文 自从学了前端的基础,自认为是没什么css是能难倒我的,可是事实是,世界上没有绝对简单的事情,实际上还有好多的东西等待我们去发掘. 详解 1.有些浏览器不完全支持css3,现在可以用 modern ...

  7. Hibernate 与Mybatis之比较

    1. hibernate是全自动,而mybatis是半自动.hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql.而mybat ...

  8. LazyTableImages范例解析

    近来想了解iPhone的多线程处理,查阅到了官方范例LazyTableImages,发现代码中有不仅有多线程处理,还有XML解析和异步下载图片,感觉官方例子真是全面啊,便花了时间好好研究下. Lazy ...

  9. BUPT复试专题—字符串转换(2013计院)

    题目描述 我们将仅由若干个同一小写字母构成的字符串称之为简单串,例如"aaaa"是一个简单串,而"abcd"则不是简单串.现在给你一个仅由小写字母组成的字符串, ...

  10. C++常用字符串分割方法

    一.用strtok函数进行字符串分割 原型: char *strtok(char *str, const char *delim); 功能:分解字符串为一组字符串. 参数说明:str为要分解的字符串, ...