题目链接:http://poj.org/problem?id=2195

Time Limit: 1000MS Memory Limit: 65536K

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
转载请注明出处:優YoU http://blog.csdn.net/lyy289065406/article/details/6732762

大致题意:
给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致。man每移动一格需花费$1(即单位费用=单位距离),一间house只能入住一个man。现在要求所有的man都入住house,求最小费用。

构图:
把man作为一个顶点集合U,house作为另一个顶点集合V,把U中所有点到V中所有点addedge{from∈U,to∈V,cap=1,cost=两点间哈密顿距离},构成一个多源多汇的二分图。
构造一个超级源点s和超级汇点t:s与U中所有点相连,费用为0,容量为1;V中所有点与t相连,费用为0,容量为1。

这种构图思路很简单,我们建立起的二分图:

不难想象,maxflow必然等于the number of men(or the number of houses),在上图的例子中,即为3;

由于我们在所有man点与house点间建立的边容量为1,显然,最大流保证了:

  ①所有man都能到house里;

  ②一个man只进到一间house,一间house只有一个man;

就像在上图中,最大流的情况下,每个m[i]只能选一个H[j],而且i,j也不能重复;

这恰好就满足了题目所给的要求,然后,只要我们在m[i]到H[j]的边上加上cost=Hamiltonian_distance(m[i],H[j]),求出最小费用就是答案啦。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<queue>
#define MAXN 203
#define INF 0x3f3f3f3f
using namespace std;
struct Edge{
int u,v,c,f,a;
};
struct MCMF
{
int s,t;
vector<Edge> E;
vector<int> G[MAXN];
int vis[MAXN];
int d[MAXN];
int pre[MAXN];
int aug[MAXN];
void init(int l,int r)
{
for(int i=l;i<=r;i++) G[i].clear();
E.clear();
}
void addedge(int from,int to,int cap,int cost)
{
E.push_back((Edge){from,to,cap,,cost});
E.push_back((Edge){to,from,,,-cost});
int m=E.size();
G[from].push_back(m-);
G[to].push_back(m-);
}
bool SPFA(int s,int t,int &flow,int &cost)
{
memset(d,INF,sizeof(d));
memset(vis,,sizeof(vis));
d[s]=, vis[s]=, pre[s]=, aug[s]=INF;
queue<int> q;
q.push(s);
while(!q.empty())
{
int now=q.front(); q.pop();
vis[now]=;
for(int i=;i<G[now].size();i++)
{
Edge& e=E[G[now][i]];
int nex=e.v;
if(e.c>e.f && d[nex]>d[now]+e.a)
{
d[nex]=d[now]+e.a;
pre[nex]=G[now][i];
aug[nex]=min(aug[now],e.c-e.f);
if(!vis[nex])
{
q.push(nex);
vis[nex]=;
}
}
}
}
if(d[t]==INF) return ;
flow+=aug[t];
cost+=d[t]*aug[t];
for(int i=t;i!=s;i=E[pre[i]].u)
{
E[pre[i]].f+=aug[t];
E[pre[i]^].f-=aug[t];
}
return ;
} int mincost()
{
int flow=,cost=;
while(SPFA(s,t,flow,cost));
return cost;
}
}mcmf; char map[][];
struct Node{int row,col;};
int Hami_dist(Node a,Node b){return abs(a.row-b.row) + abs(a.col-b.col);} int main()
{
int N,M;//N行,M列
while(scanf("%d%d",&N,&M) && N!=)
{
vector<Node> men,houses;
for(int i=;i<=N;i++) scanf("%s",map[i]+);
for(int i=;i<=N;i++)
{
for(int j=;j<=M;j++)
{
if(map[i][j]=='m') men.push_back((Node){i,j});
if(map[i][j]=='H') houses.push_back((Node){i,j});
}
}
int n=men.size();
mcmf.init(,*n+);
mcmf.s=, mcmf.t=*n+;
for(int i=;i<n;i++)
{
mcmf.addedge(mcmf.s,i+,,);
for(int j=;j<n;j++)
{
if(i==) mcmf.addedge(j++n,mcmf.t,,);
mcmf.addedge(i+,j++n,,Hami_dist(men[i],houses[j]));
}
}
printf("%d\n",mcmf.mincost());
}
}

POJ 2195 - Going Home - [最小费用最大流][MCMF模板]的更多相关文章

  1. POJ 2195 Going Home 最小费用最大流 尼玛,心累

    D - Going Home Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Subm ...

  2. poj 2195 Going Home(最小费用最大流)

    题目:http://poj.org/problem?id=2195 有若干个人和若干个房子在一个给定网格中,每人走一个都要一定花费,每个房子只能容纳一人,现要求让所有人进入房子,且总花费最小. 构造一 ...

  3. 网络流--最小费用最大流MCMF模板

    标准大白书式模板 #include<stdio.h> //大概这么多头文件昂 #include<string.h> #include<vector> #includ ...

  4. poj 2351 Farm Tour (最小费用最大流)

    Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17230   Accepted: 6647 Descri ...

  5. poj2135最小费用最大流经典模板题

    Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13509   Accepted: 5125 Descri ...

  6. 把人都送到房子里的最小花费--最小费用最大流MCMF

    题意:http://acm.hdu.edu.cn/showproblem.php?pid=1533 相邻的容量为inf,费用为1,S到m容量为1,费用为0 ,H到T容量为1,费用为0. 建图跑-最小费 ...

  7. POJ 2157 Evacuation Plan [最小费用最大流][消圈算法]

    ---恢复内容开始--- 题意略. 这题在poj直接求最小费用会超时,但是题意也没说要求最优解. 根据线圈定理,如果一个跑完最费用流的残余网络中存在负权环,那么顺着这个负权环跑流量为1那么会得到更小的 ...

  8. poj 2135 Farm Tour 最小费用最大流建图跑最短路

    题目链接 题意:无向图有N(N <= 1000)个节点,M(M <= 10000)条边:从节点1走到节点N再从N走回来,图中不能走同一条边,且图中可能出现重边,问最短距离之和为多少? 思路 ...

  9. POJ 3680: Intervals【最小费用最大流】

    题目大意:你有N个开区间,每个区间有个重量wi,你要选择一些区间,使得满足:每个点被不超过K个区间覆盖的前提下,重量最大 思路:感觉是很好想的费用流,把每个区间首尾相连,费用为该区间的重量的相反数(由 ...

随机推荐

  1. APP图标制作以及替换步骤

    1 首先要有一张1024X1024像素以上的的大图片(长宽最好相等)   2 如果app图标需要的是圆角的,那先通过以下这个工具转换一下: http://www.360doc.com/content/ ...

  2. Shiro集成Spring

    本篇博客主要讲述的是两者的集成.不涉及到各自的详细细节和功能. 因为官方给出的文档不够具体,对新手而言通过官方文档还不可以非常快的搭建出SpringShiro的webproject.本博客将通过实际的 ...

  3. 5 -- Hibernate的基本用法 --1 3 流行的ORM框架简介

    ⊙ JPA : JPA本身只是一种ORM规范,并不是ORM产品.它是Java EE规范制定者向开源世界学习的结果.JPA实体与Hibernate PO十分相似,甚至JPA实体完全可作为Hibernat ...

  4. 解决win10休眠后无法唤醒

    在控制面板-电源选项-编辑计划设置-高级电源设置中把"睡眠"的选项中休眠调整为从不,"电源按键和盖子"选项中也都设为睡眠,这样使得无论你是使用电池还是电源,系统 ...

  5. git push 问题汇总

    Q:git push时卡死 这个问题找的快要放弃的时候... A: git config --global http.postBuffer [via] Q:git push 报错 Counting o ...

  6. MyBatis入门程序之表关联

    一.一对一查询(ResultType比较简单,只需要指向扩展的类:ResultMap逐个匹配比较麻烦,可以配置属性autoMapping="true",还可以可以实现延迟加载) 1 ...

  7. Mybatis数据库连接报错:对实体 "characterEncoding" 的引用必须以 ';' 分隔符结尾

    Mybatis数据库连接报错:对实体 "characterEncoding" 的引用必须以 ';' 分隔符结尾 ============================== 蕃薯耀 ...

  8. CPU特性漏洞测试(Meltdown and Spectre)

    2018年1月4日,国外安全研究人员披露了名为"Meltdown"和"Spectre"两组CPU特性漏洞,该漏洞波及到近20年的Intel, AMD, Qual ...

  9. (原创)Android Binder设计与实现 - 实现篇(1)

    本文属于原创作品,转载请注明出处并放于明显位置,原文地址:http://www.cnblogs.com/albert1017/p/3849585.html 前言 在学习Android的Binder机制 ...

  10. Jquery-无法有效获取当前窗口高度

    今天碰到个很奇怪的事情,那就是滚动条往下滚动时候没有触发提示,反而是往上滚动的时候,触发了提示.百思不得其解,尤其是拿了美工大大的切图过来,一点问题都没有. 那么就进行console.log输出查看了 ...