POJ 2195 Going Home 二分图的最大权匹配

Going Home

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 25567   Accepted: 12838

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

题意:

有k个人,k间房子,每人进入一个房子,求最小的总距离
分析:

关键在于建图:

源点为0,汇点为2*n+1,n为房子个数(房子数等于人数);

源点到每个人建立一条容量为1,费用为0的边;

每个人到每个房子建立一条容量为1,费用为两者距离的边;

每个人到汇点建立一条容量为1,费用为0的边;

然后跑一遍最小费用最大流即可

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<cstdio>
#include<string>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#define mod 998244353
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long ll;
#define MAXN 1003
#define MAXM 40004
//最小费用最大流
struct Edge{int to,next;int flow,cost,cap;
}edge[MAXM];
int tol,head[MAXN];
void init()
{tol=0;memset(head,-1,sizeof head);
}
void addEdge(int u,int v,int cap,int cost){edge[tol].to=v;edge[tol].cap=cap;edge[tol].cost=cost;edge[tol].flow=0;edge[tol].next=head[u];head[u]=tol++;edge[tol].to=u;edge[tol].cap=0;edge[tol].cost=-cost;edge[tol].flow=0;edge[tol].next=head[v];head[v]=tol++;
}bool inq[MAXN];//标记是否点是否在队列
int dis[MAXN];//最短距离
int pre[MAXN];//记录路径
int q[MAXN*10];//队列
//单位费用可能是负值,所以用SPFA
bool spfa(int st,int en)
{memset(inq,0,sizeof inq);memset(dis,INF,sizeof dis);memset(pre,-1,sizeof pre);int rear=0,front=0;dis[st]=0;inq[st]=true;q[front++]=st;while(rear<front){int u=q[rear++];inq[u]=false;for(int e=head[u];e!=-1;e=edge[e].next){int v=edge[e].to;if(edge[e].cap>edge[e].flow&&dis[v]>dis[u]+edge[e].cost){dis[v]=dis[u]+edge[e].cost;pre[v]=e;//表示边e-->v,e就是v的前驱if(!inq[v])inq[v]=true,q[front++]=v;}}}return pre[en]!=-1;
}
int minCostMaxFlow(int st,int en,int &cost,int &flow)
{//如果能找到从源点到汇点的最短路,说明还没有达到最小费用最大流while(spfa(st,en)){int Min=INF;//最小残余流量//沿着当前路径返回for(int i=pre[en];i!=-1;i=pre[edge[i^1].to]){int rem=edge[i].cap-edge[i].flow;Min=Min>rem?rem:Min;}for(int i=pre[en];i!=-1;i=pre[edge[i^1].to]){edge[i].flow+=Min;//正向边添加残余流量edge[i^1].flow-=Min;//反向边减少残余流量cost+=Min*edge[i].cost;}flow+=Min;}
}
//以上为最小费用最大流模板int n,m;
struct point{int x,y;
}house[MAXN],men[MAXN];
char str[110];
int main()
{while(scanf("%d%d",&n,&m)&&n&&m){init();int houseNum=1,menNum=1;for(int i=0;i<n;i++){scanf("%s",str);for(int j=0;j<m;j++){if(str[j]=='H')house[houseNum].x=i,house[houseNum].y=j,houseNum++;if(str[j]=='m')men[menNum].x=i,men[menNum].y=j,menNum++;}}int st=0;int en=houseNum+menNum-1;for(int i=1;i<menNum;i++){for(int j=1;j<houseNum;j++){int w=abs(men[i].x-house[j].x)+abs(men[i].y-house[j].y);addEdge(i,menNum+j-1,1,w);}}for(int i=1;i<menNum;i++){addEdge(0,i,1,0);addEdge(menNum+i-1,en,1,0);}int cost=0,flow=0;minCostMaxFlow(st,en,cost,flow);printf("%d\n",cost);}
}

POJ2195 Going Home 最小费用最大流相关推荐

  1. POJ-2195(最小费用最大流)

    题意:二分图最小权匹配. 构图:S向左边的点连容量1,费用0的边,右边的点向T连容量1,费用0的边,点之间连容量1,费用为边权的边.最小费用最大流. 注意: 1.100*100的方格中有10000个点 ...

  2. 最小费用最大流及习题(poj)

    该算法讲解来源:https://www.cnblogs.com/gtarcoder/p/4890739.html 最小费用最大流 通过EK,Dinic,ISAP算法可以得到网络流图中的最大流,一个网络 ...

  3. 乌鲁木齐网络赛J题(最小费用最大流模板)

    ACM ICPC 乌鲁木齐网络赛 J. Our Journey of Dalian Ends 2017-09-09 17:24 243人阅读 评论(0) 收藏 举报  分类: 网络流(33)  版权声 ...

  4. POJ - 2516 Minimum Cost 最小费用最大流

    题目链接 题意:给n,m,k表示商店数,储存店数,种类数 然后给n*k表示每个水果店需求每种种类的数量: 表示成 need[i][j] 再给m*k表示每个储存店每种种类数量: 表示成store[i][ ...

  5. pku The Windy's KM最小权匹配 or 最小费用最大流

    http://poj.org/problem?id=3686 题意: 给定n个玩具,有m个车间,给出每个玩具在每个车间的加工所需的时间mat[i][j]表示第i个玩具在第j个车间加工所需的时间,规顶只 ...

  6. c语言最小费用流_策略算法工程师之路-图优化算法(一)(二分图amp;最小费用最大流)...

    目录 1.图的基本定义 2.双边匹配问题 2.1 二分图基本概念 2.2 二分图最大匹配求解 2.3 二分图最优匹配求解 2.4 二分图最优匹配建模实例 2.4.1 二分图最优匹配在师生匹配中的应用 ...

  7. 有源汇上下界最小费用可行流 ---- P4553 80人环游世界(拆点 + 有源汇上下界最小费用可行流)

    题目链接 题目大意: 解题思路: 又是一道裸题 . 首先它要求第iii个点只经过ViViVi那么我们就拆点ai,ai+na_i,a_{i+n}ai​,ai+n​一个点为入点,一个为出点这条边的流量范围 ...

  8. 有源汇上下界最小费用可行流 ---- P4043 [AHOI2014/JSOI2014]支线剧情(模板)

    题目链接 题目大意: 解题思路: 有源汇上下界最小费用可行流模板题目来着 先建出一个有源汇上下界可行流的图,然后注意建图的时候要把每条边的下界的费用提前加到ans里面 然后再对图跑费用流,就是补齐费用 ...

  9. Doctor NiGONiGO’s multi-core CPU(最小费用最大流模板)

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=693 题意:有一个 k 核的处理器和 n 个工作,全部的工作都须要在一个核上处理一个单位的 ...

最新文章

  1. 云职教课堂计算机文化基础,2020智慧职教云课堂计算机文化基础答案最新最全单元测试答案...
  2. 使用 Python 的基于边缘和基于区域的分割
  3. go语言学习,channel消费者和生产者
  4. 【干货分享】云服务平台的架构及优势(上)
  5. C++之菱形继承的解决之道
  6. 解决beautifulsoup代码无效问题
  7. Markdown-数学公式语法
  8. 这应该是目前最快速有效的ASP.NET Core学习方式(视频)
  9. 佰腾科技:专利大数据的云上裂变之路
  10. mysql简单语句_MYSQL常用简单语句
  11. python滚动条翻页爬取数据_[Selenium2+python2.7][Scrap]爬虫和selenium方式下拉滚动条获取简书作者目录并且生成Markdown格式目录...
  12. linux 卸载 java_Linux安装卸载JDK完整步骤
  13. 2019.8.29C++工作错误记录——Socket编程中出现ws2def.h文件“应输入标识符”或“重定义”问题(VS2015)
  14. 板翅式换热器翅片表面传热与阻力特性性能分析
  15. 路由器自适应算法OSPF和RIP协议(通俗理解)
  16. 参考文献起止页码怎么写_参考文献规范写法
  17. 弹出USB大容量存储设备时出问题“该设备正在使用中”
  18. 音视频技术开发周刊 | 164
  19. 学会了C语言究竟能干什么呢?
  20. 游戏建模过程中如何布线?建模布线原理和技巧

热门文章

  1. 学习react心得及总结
  2. '$.browser.msie' 为空或不是对象
  3. python制作好看的界面_【一点资讯】Python界面如何漂亮的展示树形结构,PyQt5控件之QTreeWidget详解 www.yidianzixun.com...
  4. lua如何打印行号_双11购物清单,你打印了吗?9个打印技巧解密Excel打印问题,每一个难题都可以在这里找到答案...
  5. python字典高级用法_Python 字典的高级用法
  6. tftp c++ 上传_如何在 Fedora 上建立一个 TFTP 服务器
  7. python列表推导式格式_Python列表推导式(for表达式)及用法
  8. mysql csv 表头_mysql 导出CSV文件 并带表头的方法
  9. 已经围上为何不算目_在湖人打球顺风顺水,戴维斯为何还要亏本卖掉洛杉矶豪宅?...
  10. java swing form_在java swing中创建表单最简单的方法是什么?