POJ2195(KB11-D 最小费用最大流)

Going Home

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 23515   Accepted: 11853

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

Pacific Northwest 2004

所有的房子和超级源点连边,容量为1,费用为0。

所有的人和超级汇点连边,容量为1,费用为0。

所有的房子和所有的人相互连边,容量为1,费用为房子和人的曼哈顿距离。

  1 //2017-08-24
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <cmath>
  8
  9 using namespace std;
 10
 11 const int N = 1000;
 12 const int M = 100000;
 13 const int INF = 0x3f3f3f3f;
 14 int head[N], tot;
 15 struct Edge{
 16     int to, next, c, w;//c为容量,w为单位费用
 17 }edge[M];
 18
 19 void add_edge(int u, int v, int c, int w){
 20     edge[tot].c = c;
 21     edge[tot].w = w;
 22     edge[tot].to = v;
 23     edge[tot].next = head[u];
 24     head[u] = tot++;
 25
 26     edge[tot].c = 0;
 27     edge[tot].w = -w;
 28     edge[tot].to = u;
 29     edge[tot].next = head[v];
 30     head[v] = tot++;
 31 }
 32
 33 bool vis[N];
 34 int pre[N], dis[N];//pre记录路径,dis记录到源点的最小花费
 35 struct MinCostMaxFlow{
 36     int S, T;
 37     int flow, cost;
 38     void init(int _S, int _T){
 39         S = _S;
 40         T = _T;
 41         tot = 0;
 42         memset(head, -1, sizeof(head));
 43     }
 44     bool spfa(){
 45         memset(vis, 0, sizeof(vis));
 46         memset(dis, INF, sizeof(dis));
 47         dis[S] = 0;
 48         vis[S] = 1;
 49         queue<int> que;
 50         que.push(S);
 51         while(!que.empty()){
 52             int u = que.front();
 53             que.pop();
 54             for(int i = head[u]; i != -1; i = edge[i].next){
 55                 int v = edge[i].to;
 56                 if(edge[i].c > 0 && dis[v] > dis[u]+edge[i].w){
 57                     dis[v] = dis[u] + edge[i].w;
 58                     pre[v] = i;
 59                     if(!vis[v]){
 60                         vis[v] = true;
 61                         que.push(v);
 62                     }
 63                 }
 64             }
 65             vis[u] = 0;
 66         }
 67         return dis[T] != INF;
 68     }
 69     int dfs(int &flow){
 70         int u, p, sum = INF, ans = 0;
 71         for(u = T; u != S; u = edge[p^1].to){
 72             //记录路径上的最小流值
 73             p = pre[u];
 74             sum = min(sum, edge[p].c);
 75         }
 76         for(u = T; u != S; u = edge[p^1].to){
 77             p = pre[u];
 78             edge[p].c -= sum;
 79             edge[p^1].c += sum;
 80             ans += sum*edge[p].w;
 81         }
 82         flow += sum;
 83         return ans;
 84     }
 85     int maxflow(){
 86         cost = 0, flow = 0;
 87         while(spfa()){//寻找增广路并增广
 88             cost += dfs(flow);
 89         }
 90         return cost;
 91     }
 92 }mcmf;
 93
 94 string grid[N];
 95 int x[N], y[N];
 96
 97 int main()
 98 {
 99     std::ios::sync_with_stdio(false);
100     //freopen("inputD.txt", "r", stdin);
101     int n, m;
102     while(cin>>n>>m && (n || m)){
103         int cnt_m = 0, cnt_h = 0;
104         int s = N-2, t = N-3;
105         mcmf.init(s, t);
106         for(int i = 0; i < n; i++){
107             cin>>grid[i];
108             for(int j = 0; j < m; j++){
109                 if(grid[i][j] == ‘H‘){
110                     add_edge(s, cnt_h, 1, 0);
111                     x[cnt_h] = i;
112                     y[cnt_h++] = j;
113                 }
114             }
115         }
116         for(int i = 0; i < n; i++){
117             for(int j = 0; j < m; j++){
118                 if(grid[i][j] == ‘m‘){
119                     add_edge(cnt_h+cnt_m, t, 1, 0);
120                     for(int k = 0; k < cnt_h; k++){
121                         add_edge(k, cnt_h+cnt_m, 1, abs(i-x[k])+abs(j-y[k]));
122                     }
123                     cnt_m++;
124                 }
125             }
126         }
127         cout<<mcmf.maxflow()<<endl;
128     }
129
130     return 0;
131 }
时间: 2024-11-08 19:10:17

POJ2195(KB11-D 最小费用最大流)的相关文章

POJ-2195 Going Home(最小费用最大流模板)

题目链接:POJ-2195 Going Home 题意 给出$N$行$M$列的网格,'m'表示人,'H'表示房子,且'm'和'H'的数量相同,一个人只能进一间房子,一间房子也只能给一个人进去,人可走上下左右四个方向,现在要让所有人进入房子,求最短路径和. 思路 这是一个二分图带权最小匹配问题,可直接用最小费用最大流求解. 源点向人各连一条容量为1,费用为0的边,每个人向每间房子连容量为1,费用为距离的边,每间房子向汇点连容量为1,费用为0的边,然后跑最小费用最大流即可. 代码实现 #includ

最小费用最大流 POJ2195-Going Home

网络流相关知识参考: http://www.cnblogs.com/luweiseu/archive/2012/07/14/2591573.html 出处:優YoU http://blog.csdn.net/lyy289065406/article/details/6732762 大致题意: 给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致.man每移动一格需花费$1(即单位费用=单位距离),一间house只能入住一个man.现在要求所有的man都入住hou

【BZOJ3876】【Ahoi2014】支线剧情 有下界的最小费用最大流

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43025375"); } [BZOJ2324]营救皮卡丘 这道题也是一道有下界的最小费用最大流. 我的题解地址:http://blog.csdn.net/vmurder/article/details/41378979 这道题其实就是模板题. 我的处理

POJ 3686.The Windy&#39;s 最小费用最大流

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5477   Accepted: 2285 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receives N orders for toys. The ma

P3381 【模板】最小费用最大流

P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含四个正整数ui.vi.wi.fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi. 输出格式: 一行,包含两个整数,依次为最大流量和在最大流量情况下的

C++之路进阶——最小费用最大流(支线剧情)

F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  hyxzc Logout 捐赠本站 Notice:由于本OJ建立在Linux平台下,而许多题的数据在Windows下制作,请注意输入.输出语句及数据类型及范围,避免无谓的RE出现. 3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 542  Solved: 332[Submit

hdu 4494 Teamwork 最小费用最大流

Teamwork Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4494 Description Some locations in city A has been destroyed in the fierce battle. So the government decides to send some workers to repair these location

POJ - 2195 Going Home(最小费用最大流)

1.N*M的矩阵中,有k个人和k个房子,每个人分别进入一个房子中,求所有人移动的最小距离. 2.人看成源点,房子看成汇点,求最小费用最大流. 建图-- 人指向房子,容量为1,费用为人到房子的曼哈顿距离. 建立超级源点和超级汇点:超级源点指向人,容量为1,费用为0:超级汇点指向房子,容量为1,费用为0. 求超级源点到超级汇点的最小费用最大流即可. ps:容量为什么都设为1?---有待研究.. 3. 1.Bellman-Ford: #include<iostream> #include<st

hdu 1853 Cyclic Tour 最小费用最大流

题意:一个有向图,现在问将图中的每一个点都划分到一个环中的最少代价(边权和). 思路:拆点,建二分图,跑最小费用最大流即可.若最大流为n,则说明是最大匹配为n,所有点都参与,每个点的入度和出度又是1,所以就是环. /********************************************************* file name: hdu1853.cpp author : kereo create time: 2015年02月16日 星期一 17时38分51秒 *******

最小费用最大流

Farm Tour http://poj.org/problem?id=2135 建图再说吧 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<map> 6 #include<stack> 7 #include<queue> 8 #include<vector> 9 #include&l