题目链接: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. Spring中可以复用的工具类&特性记录

    Spring 里有用工具类: GenericTypeResolver 解析泛型类型.核心逻辑还是调用 ResolvableTypeResolvableType 解析泛型类型 BeanWrapper 利 ...

  2. 64位Oracle 11g 使用PL/SQL

    Oracle 11g和PL/SQL安装完后,发现打开PL/SQL并不能连接Oracle数据库! [第一回合]完败! 先是在网上找解决方法,说是需要使用Net Configuration Assista ...

  3. Android Studio 修改Logcat的颜色

    在Android Studio里面默认的logcat显示颜色是灰色的,不同等级的log是没有颜色分别的,如图 这一点远不如Eclipse好看,但是Android Studio的logcat的颜色其实也 ...

  4. 不作死就不会死,微软强行插入NO-IP

    微软啊微软,你这是何苦来着. 事情经过大致是这样的,微软向美国法院提出起诉No-IP名下22个常用的子域名被恶意软件的作者滥用,要求法官裁定由微软接管No-IP名下的这22个子域名,以便其可以过滤恶意 ...

  5. Studio更新

    其实最主要的是下面三个步骤: 1.更新As工程为3.0 2.必须升级gradle到4.0以上 3.buildToolsVersion升级到26.0.0 4.在gradle.properties中配置版 ...

  6. 升级nodejs至最新

    网上找出了很多升级nodejs版本的方法,都不太好用,直至发现这个: 在命令行窗口中执行:where node: 然后在nodejs官网中下载最新版本,将刚才目录下node.exe替换掉: 最后执行: ...

  7. gozmq的安装与使用

    1. 安装zmq 下载Windows版安装或linux版本并执行安装命令: tar zxvf zeromq-4.1.6.tar.gz cd zeromq-4.1.6 ./configure make ...

  8. VC调用DLL

    VC调用DLL   调用DLL有两种方法:静态调用和动态调用. (一).静态调用其步骤如下: 1.把你的youApp.DLL拷到你目标工程(需调用youApp.DLL的工程)的Debug目录下; 2. ...

  9. 《Lua程序设计》第3章 表达式 学习笔记

    3.1 算术操作符“+”(加法).“-”(减法).“*”(乘法).“/”(除法).“^”(指数).“%”(取模).3.2 关系运算符< > <= >= == ~=3.3 逻辑操 ...

  10. React Native 开发工具篇

    正文 概述:开发RN的工具有很多,选择性也比较多,比如Facebook专门为React开发的IDE:Nuclide,还有做前端比较熟悉的WebStorm.Sublime Text 3.VS Code等 ...