POJ 2195 一人一房 最小费用流 建图 水题
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 21010 | Accepted: 10614 |
Description
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
Output
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
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const int mod = 1000000007;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const int big=50000;
int max(int a,int b) {return a>b?a:b;};
int min(int a,int b) {return a<b?a:b;};
const int N = 70;
const int M=10000+100;
struct edge{
int to,cap,cost,rev;
}; vector<edge> G[1005];
int dist[1005],inq[1005],prev[1005],prel[1005];
struct Point{
int x,y;
}; int n,m,x,y,c,cnth,cntm;
Point house[105],men[105]; void add_edge(int u,int v,int cap,int cost)
{
G[u].push_back(edge{v,cap,cost,G[v].size()});
G[v].push_back(edge{u,0,-cost,G[u].size()-1});
} int mincost(int s,int t,int f)
{
int ans=0;
while(f>0)
{
memset(dist,inf,sizeof(dist));
memset(inq,0,sizeof(inq));
dist[s]=0;
queue<int> q;
q.push(s);
inq[s]=1;
MM(prev,-1);
while(!q.empty())
{
int u=q.front();
q.pop();inq[u]=0;
for(int j=0;j<G[u].size();j++)
{
edge &e=G[u][j];
if(e.cap>0&&dist[e.to]>dist[u]+e.cost)
{
dist[e.to]=dist[u]+e.cost;
prev[e.to]=u;
prel[e.to]=j;
if(!inq[e.to])
{
q.push(e.to);
inq[e.to]=1;
}
}
}
}
for(int i=t;i>s;)
{
int f=prev[i];
if(f==-1) return -1;
int j=prel[i];
G[f][j].cap-=1;
G[i][G[f][j].rev].cap+=1;
ans+=G[f][j].cost;
i=prev[i];
}
f-=1;
}
return ans;
} void build()
{
for(int i=0;i<=cnth+cntm+1;i++) G[i].clear();
for(int i=1;i<=cntm;i++)
add_edge(0,i,1,0);
for(int i=1;i<=cnth;i++)
add_edge(cntm+i,cntm+cnth+1,1,0);
for(int i=1;i<=cntm;i++)
for(int j=1;j<=cnth;j++)
{
int dis=abs(house[j].x-men[i].x)+abs(house[j].y-men[i].y);
add_edge(i,j+cntm,1,dis);
}
} char s[105][105];
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m)&&(n||m))
{
cnth=cntm=0;
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]);
for(int j=0;j<m;j++)
if(s[i][j]=='H')
house[++cnth]=(Point){i,j+1};
else if(s[i][j]=='m')
men[++cntm]=(Point){i,j+1};
}
build();
printf("%d\n",mincost(0,cnth+cntm+1,cnth));
}
return 0;
}
分析:建图有一点点技术含量,人放左边,门放右边,加一个源点与汇点,然后跑一跑大小为人数(门数)的最小费用流就好,
POJ 2195 一人一房 最小费用流 建图 水题的更多相关文章
- poj 3281 Dining 网络流-最大流-建图的题
题意很简单:JOHN是一个农场主养了一些奶牛,神奇的是这些个奶牛有不同的品味,只喜欢吃某些食物,喝某些饮料,傻傻的John做了很多食物和饮料,但她不知道可以最多喂饱多少牛,(喂饱当然是有吃有喝才会饱) ...
- POJ 2195 Going Home【最小费用流 二分图最优匹配】
题目大意:一个n*m的地图,上面有一些人man(m)和数量相等的house(H) 图上的距离为曼哈顿距离 问所有人住进一所房子(当然一个人住一间咯)距离之和最短是多少? 思路:一个人一间房,明显是二分 ...
- poj 1149 Pigs 网络流-最大流 建图的题目(明天更新)-已更新
题目大意:是有M个猪圈,N个顾客,顾客要买猪,神奇的是顾客有一些猪圈的钥匙而主人MIRKO却没有钥匙,多么神奇?顾客可以在打开的猪圈购买任意数量的猪,只要猪圈里有足够数量的猪.而且当顾客打开猪圈后mi ...
- POJ 2226 最小点覆盖(经典建图)
Muddy Fields Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8881 Accepted: 3300 Desc ...
- joj 2453 candy 网络流建图的题
Problem D: Candy As a teacher of a kindergarten, you have many things to do during a day, one of whi ...
- BZOJ 1303 CQOI2009 中位数图 水题
1303: [CQOI2009]中位数图 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2340 Solved: 1464[Submit][Statu ...
- poj 2195 Going Home(最小费用流)
题目链接:http://poj.org/problem?id=2195 题目大意是给一张网格,网格中m代表人,h代表房子,网格中的房子和人数量相等,人可以向上向下走,每走1步花费加1,每个房子只能住一 ...
- POJ 2312Battle City(BFS-priority_queue 或者是建图spfa)
/* bfs搜索!要注意的是点与点的权值是不一样的哦! 空地到空地的步数是1, 空地到墙的步数是2(轰一炮+移过去) 所以用到优先队列进行对当前节点步数的更新! */ #include<iost ...
- POJ 1161 Walls(Floyd , 建图)
题意: 给定n个城市, 然后城市之间会有长城相连, 长城之间会围成M个区域, 有L个vip(每个vip会处于一个城市里)要找一个区域聚会, 问一共最少跨越多少个长城. 分析: 其实这题难就难在建图, ...
随机推荐
- Redis缓存击穿
缓存击穿 缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞. 比如在做 ...
- 蚂蚁分类信息商家发布文章、商品外链及远程图片自动添加nofollow属性
蚂蚁商户发布文章.商品是可以添加外链或者直接用外部图片,但是这对分类网站运营不利. 所以要对外链进行过滤,演示网站保洁,蚂蚁分类的源码. 下面就说下怎么处理自动给外链自动加上nofollow属性. 1 ...
- GitHub从小白到熟悉<三>
上传文件
- Ansible 系统概述与部署
Ansible 系统概述 Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具.它用Python写成,类似于saltstack和Puppet但是有一个不同和优点是我们不需要在节点中安装 ...
- Nginx启动错误 Failed to read PID from file /run/nginx.pid 的处理方法
问题产生原因 因为 nginx 启动需要一点点时间,而 systemd 在 nginx 完成启动前就去读取 pid file 造成读取 pid 失败 解决方法 让 systemd 在执行 ExecSt ...
- vue运行碰到的问题
Expected indentation of 0 spaces but found 2 解决方案: 文件中加入"indent": ["off", 2]就可以了 ...
- java实现spark常用算子之filter
import org.apache.spark.SparkConf;import org.apache.spark.api.java.JavaRDD;import org.apache.spark.a ...
- 小程序之textarea层级最高问题
1.textarea位于底部固定定位按钮下方,会导致点击底部按钮,textarea获取到焦点. 解决方法如下 view与textarea之间在聚焦和失去焦点进行切换 cursor-spacing是te ...
- Dedecms 生成速度慢 的解决办法
从dedecms官网论坛找到个合适的代码 include/inc/inc_fun_SpGetArcList.php for($i=0;$i<$ridnum;$i++){ if($tpsql==& ...
- 【异常】~/.bash_profile:source:44: no such file or directory: /usr/local/Cellar/nvm/0.34.0/nvm.sh
1 异常信息 /Users/zhangjin/.bash_profile:source:: no such file or directory: /usr/local/Cellar/nvm//nvm. ...