题目链接: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. bzoj2120 数颜色 莫队 带修改

    [bzoj2120]数颜色 Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔 ...

  2. spring mvc 单元测试示例

    import java.awt.print.Printable; import java.io.IOException; import javax.servlet.http.HttpServletRe ...

  3. 跳蚤 BZOJ 4310

    跳蚤 [问题描述] 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最 ...

  4. maven编码gbk的不可映射字符

    如图,老是出现这个错误,百度说是打开源文件,更改编码格式,或者是更改File Encodings 的编码格式,或者是更改java compiler --use computer为eclipse, 都不 ...

  5. php——解决中文乱码问题

    一般写代码的时候遇到中文乱码的问题还是比较烦躁的,下面是我总结的几种中文乱码的解决办法: 1:php在头部设置header设置编码方式: header('Content-type:text/html; ...

  6. POJ 1509 Glass Beads【字符串最小表示法】

    题目链接: http://poj.org/problem?id=1509 题意: 求循环字符串的最小表示. 分析: 浅析"最小表示法"思想在字符串循环同构问题中的应用 判断两字符串 ...

  7. 2017-10-29-morning-清北模拟赛

    T1 遭遇 #include <algorithm> #include <cstdio> #include <cmath> inline void read(int ...

  8. Linux配置防火墙添加端口(Ubuntu/Debian无法使用此方法)

    注意:Ubuntu/Debian无法使用此方法 1.打开iptables vi /etc/sysconfig/iptables 2.添加防火墙规则 规则参考:http://www.cnblogs.co ...

  9. BUPT复试专题—排序(2009)

    题目描述 查找序列a 中小于 b 的第 i 个数的数的个数 输入 输入有多组,每组四行第一行:序列a个数N第二行:(序列a的)N个数,升序排列第三行:序列b个数M 第四行:(序列b的)M个数,升序排列 ...

  10. win7下 安装 source code pro

    转: http://my.oschina.net/yearnfar/blog/325107 source code pro 字体安装, 一. 去 https://github.com/adobe-fo ...