最小费用流 poj2195

Going Home

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 17955   Accepted: 9145

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扫描路径得到人和房子的坐标,相减得所费路程,然后建边最小费用流即可
  1 #include<cstdio>
  2 #include <queue>
  3 #include <algorithm>
  4 #include <assert.h>
  5 #include <cstring>
  6 using namespace std;
  7 const int inf=0x7fffffff;
  8 int n,m;
  9
 10 char maz[101][101];
 11 int man[101][2];
 12 int house[101][2];
 13 int hlen,mlen;
 14
 15
 16 const int sups=201;
 17 const int supt=202;
 18
 19 int cost[203][203];
 20 int f[203][203];
 21 int e[203][203];
 22 int len[203];
 23
 24 int d[203];
 25 int pre[203];
 26 bool vis[203];
 27
 28 queue<int  >que;
 29
 30 int main(){
 31     while(scanf("%d%d",&n,&m)==2&&n&&m){
 32 input:
 33         hlen=mlen=0;
 34         gets(maz[0]);
 35         for(int i=0;i<n;i++){
 36             gets(maz[i]);
 37         }
 38         for(int i=0;i<n;i++){
 39             for(int j=0;j<m;j++){
 40                 if(maz[i][j]==‘m‘){
 41                     man[mlen][0]=i;man[mlen++][1]=j;
 42                 }
 43                 else if(maz[i][j]==‘H‘){
 44                     house[hlen][0]=i;house[hlen++][1]=j;
 45                 }
 46             }
 47         }
 48
 49         memset(f,0,sizeof(f));
 50         memset(cost,0,sizeof(cost));
 51         fill(len,len+mlen,hlen+1);fill(len+mlen,len+mlen+hlen,mlen+1);len[sups]=mlen;len[supt]=hlen;
 52 bulidedge:
 53         for(int i=0;i<mlen;i++){
 54             f[sups][i]=1;
 55             e[sups][i]=i;
 56             e[i][0]=sups;
 57             for(int j=0;j<hlen;j++){
 58                 e[i][j+1]=j+mlen;
 59                 e[j+mlen][i+1]=i;
 60                 f[i][j+mlen]=1;
 61                 cost[i][j+mlen]=abs(man[i][0]-house[j][0])+abs(man[i][1]-house[j][1]);
 62                 cost[j+mlen][i]=-cost[i][j+mlen];
 63             }
 64         }
 65         for(int j=0;j<hlen;j++){
 66             e[supt][j]=j+mlen;
 67             e[j+mlen][0]=supt;
 68             f[j+mlen][supt]=1;
 69         }
 70
 71 mincostflow:
 72         int ans=0;
 73         int flow=mlen;
 74         while(flow>0){
 75             fill(d,d+203,inf);
 76             d[sups]=0;
 77             que.push(sups);
 78             while(!que.empty()){
 79                 int fr=que.front();que.pop();
 80                 vis[fr]=false;
 81                 for(int i=0;i<len[fr];i++){
 82                     int to=e[fr][i];
 83                     if(f[fr][to]>0&&d[to]>d[fr]+cost[fr][to]){
 84                         d[to]=d[fr]+cost[fr][to];
 85                         pre[to]=fr;
 86                         if(!vis[to]){
 87                             que.push(to);
 88                             vis[to]=true;
 89                         }
 90                     }
 91                 }
 92             }
 93
 94             assert(d[supt]!=inf);
 95
 96             int sub=flow;
 97             for(int i=supt;i!=sups;i=pre[i]){
 98                 sub=min(flow,f[pre[i]][i]);
 99             }
100             flow-=sub;
101             ans+=sub*d[supt];
102             for(int i=supt;i!=sups;i=pre[i]){
103                 f[pre[i]][i]-=sub;
104                 f[i][pre[i]]+=sub;
105             }
106
107         }
108         printf("%d\n",ans);
109     }
110     return 0;
111 }

最小费用流 poj2195

时间: 2024-10-15 18:39:48

最小费用流 poj2195的相关文章

[POJ2195]Going Home(带权最大匹配,KM,最小费用流)

题目链接:http://poj.org/problem?id=2195 题意:给个图,m代表人H代表房子.每一个m要有一个H,代价是曼哈顿距离.问让所有m找到房子的最小花费. 可以直接枚举m和H建二分图跑KM. 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include

POJ2195 最小费用流

题目:http://poj.org/problem?id=2195 处理出每个人到每个门的曼哈顿距离,分别建立容量为1费用为曼哈顿距离的边,在源点和每个人人之间建立容量为1费用为0的边,在门和汇点之间建立容量为1费用为0的边,然后跑最小费用流即可. 1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 #include<iostream> 6 #

poj2195&amp;&amp;hdu1533 最小费用流

这题也可以用km做,我写的代码km比费用流快很多. 最小费用流: #include<stdio.h> #include<string.h> #include<math.h> #include<queue> #include<stdlib.h> #define INF 1000000000 using namespace std; const int maxn = 1100; struct Set { int x,y; }mnum[110*110]

POJ2195 Going Home 【最小费用流】+【二分图最佳匹配】

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18169   Accepted: 9268 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 vertical

POJ 2195Going Home(网络流之最小费用流)

题目地址:POJ2195 本人职业生涯费用流第一发!!快邀请赛了,决定还是多学点东西,起码碰到简单的网络流要A掉.以后最大流费用流最小割就一块刷. 以前费用流在我心目中一直是高大上,高不可攀的形象,可这两天才发现,原来费用流就是一个spfa再加点东西...一直以为费用流会比最大流的isap要麻烦好多,毕竟多了一个费用的元素....我真的错了..仔细研究了一下,只用一个spfa确实就可以解决了... 这题是一个入门题(虽然还多了些处理..),建图思路很简单,就是将人与源点相连,流量为1,费用为0,

POJ-2195(最小费用最大流+MCMF算法)

Going Home POJ-2195 这题使用的是最小费用流的模板. 建模的时候我的方法出现错误,导致出现WA,根据网上的建图方法没错. 这里的建图方法是每次到相邻点的最大容量为INF,而花费为1,因为花费等于距离.但是需要增加一个源点和一个汇点,然后将每个人和源点相连,每个房子和汇点相连,容量都为1,费用都为0. #include<iostream> #include<algorithm> #include<cstring> #include<queue>

HDU 3488Tour(网络流之最小费用流)

题目地址:hdu3488 这题跟上题基本差不多啊....详情请戳这里. 另外我觉得有要改变下代码风格了..终于知道了为什么大牛们的代码的变量名都命名的那么长..我决定还是把源点与汇点改成source和sink吧..用s和t太容易冲突了...于是如此简单的一道题调试到了现在..sad... 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #

【bzoj1834】[ZJOI2010]network 网络扩容 最大流+最小费用流

题目描述 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. 输入 输入文件的第一行包含三个整数N,M,K,表示有向图的点数.边数以及所需要增加的流量. 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边. 输出 输出文件一行包含两个整数,分别表示问题1和问题2的答案. 样例输入 5 8 2 1 2 5 8 2 5 9

poj2135 最小费用流

添加超级源点(与点1之间的边容量为2,权值为0)和超级汇点(与点N之间的边容量为2,权值为0),求流量为2的最小费用流.注意是双向边. #include <iostream> #include <cstdio> #include <vector> #include <queue> using namespace std; const long long INF = 0x3f3f3f3f3f3f3f3f; typedef long long ll; typed