题目链接: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. mock数据。根据表中一天的数据模拟其他日期的数据

    package test; import java.sql.*; import java.text.SimpleDateFormat; import java.util.*; import java. ...

  2. Nk 1430 Fibonacci(二分矩阵乘幂)

    AC代码: #include<iostream> using namespace std; ][]; ][]; ][]; ][]; void binary(int n) { int i,j ...

  3. 洛谷 [P2575] 高手过招

    SG函数+状压记忆化搜索 观察题目发现,每一行都是独立的,只要处理出来每一行的SG值,异或起来就好 每一行的SG值可以用状压+记忆化搜索的方法来求,对位运算技术是个很大的考验 注意SG值要预处理出来, ...

  4. 【shell】shell编程(一)-入门

    如今,不会Linux的程序员都不意思说自己是程序员,而不会shell编程就不能说自己会Linux.说起来似乎shell编程很屌啊,然而不用担心,其实shell编程真的很简单.背景 什么是shell编程 ...

  5. spring-boot-nginx代理-docker-compose部署

    在本地测试,使用docker部署不用在意环境 java测试项目: web框架:spring boot 框架 项目管理:maven 数据库:redis + postgres + mongo 部署相关:n ...

  6. 最小费用最大流粗解 poj2516

    最小费用最大流,一般解法如下: 在流量基础上,每条边还有权费用,即单位流量下的所需费用.在最大流量下,求最小费用.解法:在最大流算法基础上,每次按可行流增广改为每次用spfa按最小费用(用单位费用)增 ...

  7. Eclipse、IDEA安装JavaFX

    简介 JavaFX插件 e(fx)eclipse是一组工具和必要的库,它们帮助您执行JavaFX编程,确保您已经作为插件将其安装在eclipse上了. JavaFX Scene Builder Jav ...

  8. BZOJ 4810 [Ynoi2017]由乃的玉米田 (莫队 + bitset)

    题目链接  BZOJ 4810 首先对询问离线, 莫队算法处理. 首先我们可以用bitset维护处当前区间中是否存在某个数. 对于询问1, 我们可以用 ((f >> q[i].x) &am ...

  9. RMA Sales Order – Stuck with “Awaiting Return Disposition”

    RMA Sales Order – Stuck with “Awaiting Return Disposition” Action : (Prod) ð  Login to Unix ð  su – ...

  10. SolidEdge如何打开或关闭自动标注尺寸

    工具-聪慧-自动标注尺寸