HDU 1533 Going Home (最小费用流)
题意:
一个矩阵n*m,其中有k个房子和k个人,k个人分别必须走到任意一个房子中(匹配),但是权值就是长度(非欧拉距离),求匹配完的权之和。
思路:
建图方法是,首先将k个人和k个房子分别抽出来到集合X和Y中,计算两两之间的距离,X到Y有一条边,费用为正,容量为1;Y到X也有一条边,费用为负,容量为0(其实两条边就是相反的)。添加一个源点0号到X集,添加一个汇点2*k+1号到Y集,这些费用都是0,容量都是1。
建完图就用正常的方法(EK+SPFA)来解决就行了。由于我想要让每次增广路只找到流为1的路径,所以我在2*k+1号点后面还加个点2*k+2,仅1条边,费用为0,容量为1。这样每次spfa至多也只有1流量通过到汇点了。(可不用此法,将每次spfa所得cost[end]*flow[end]就行了,因为可能流过的并不止1流量。)
#include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=+;
vector<int> vect[N];
int flow[N], cost[N], path[N], inq[N], edge_cnt;
struct node
{
int from;
int to;
int val;
int cap;
int flo;
}edge[N*];//边数要自己估计,不然就会RE void add_node(int from,int to, int val, int cap, int flo)
{
edge[edge_cnt].from=from;
edge[edge_cnt].to=to;
edge[edge_cnt].val=val;
edge[edge_cnt].cap=cap;
edge[edge_cnt].flo=flo;
vect[from].push_back(edge_cnt++);
} int spfa(int s,int e)
{
deque<int> que;
que.push_back(s);
inq[s]=;
flow[s]=INF;
cost[s]=; while(!que.empty())
{
int x=que.front();
que.pop_front();
inq[x]=;
for(int i=; i<vect[x].size(); i++)
{
node e=edge[vect[x][i]];
if(e.cap>e.flo && cost[e.to]>cost[e.from] + e.val)
{
cost[e.to]=cost[x]+ e.val;//每次的流最多只是1。
path[e.to]=vect[x][i];
flow[e.to]=min(flow[e.from], e.cap-e.flo);
if(!inq[e.to])
{
inq[e.to]=;
que.push_back(e.to);
}
}
}
}
return cost[e];
} int cal(int s,int e)
{
int ans=;
while(true)
{
memset(flow, , sizeof(flow));
memset(cost, 0x7f, sizeof(cost));
memset(path, , sizeof(path));
memset(inq, , sizeof(inq)); if(spfa(s,e)==INF) return ans;
ans+=cost[e]; int ed=e-;//连e点那条边不清空,可以保证每次至多1流。
while(ed!=s)
{
int t=path[ed];
edge[t].flo++;
edge[t^].flo--;
ed=edge[t].from;
}
}
} int main()
{
freopen("input.txt", "r", stdin);
int n, m;char ch;
while(~scanf("%d%d",&n,&m),n+m)
{
for(int i=N-; i>=; i--) vect[i].clear();
memset(edge, , sizeof(edge));
edge_cnt=;
int cnt=;
vector<pii> vect_h,vect_m; for(int i=; i<=n; i++)
for(int j=; j<=m; j++)
{
cin>>ch;
if(ch=='H') vect_h.push_back(make_pair(i,j)),cnt++;
if(ch=='m') vect_m.push_back(make_pair(i,j));
} for(int i=; i<vect_m.size(); i++)
{
int a=vect_m[i].first, b=vect_m[i].second;
for(int j=; j<vect_h.size(); j++)
{
int c=vect_h[j].first, d=vect_h[j].second;
int dis=abs(c-a)+abs(d-b); add_node(i+,cnt+j+,dis,,);
add_node(cnt+j+,i+,-dis,,);
}
} for(int i=; i<vect_m.size(); i++) //添加源点
{
add_node(,i+,,,);
add_node(i+,,,,); }
for(int j=; j<vect_h.size(); j++) //添加汇点
{
add_node(cnt+j+,cnt*+,,,);
add_node(cnt*+,cnt+j+,,,);
}
add_node(cnt*+,cnt*+, , , ); //这是为了每次只流过1。再汇点后面再加个汇点,容量是1,但是每次spfa后都不增加flow。
add_node(cnt*+,cnt*+, , , );
cout<<cal(,cnt*+)<<endl;
}
return ;
}
AC代码
HDU 1533 Going Home (最小费用流)的更多相关文章
- hdu 1533 Going Home 最小费用流
构建地图非常easy bfs预处理地图.距离的成本 来源所有m建方,流程1费0 m所有H建方,流程1距离成本 H汇点建设成为各方.流程1费0 #include<cstdio> #inclu ...
- 【HDU 1533】 Going Home (KM)
Going Home Problem Description On a grid map there are n little men and n houses. In each unit time, ...
- POJ 2195 Going Home / HDU 1533(最小费用最大流模板)
题目大意: 有一个最大是100 * 100 的网格图,上面有 s 个 房子和人,人每移动一个格子花费1的代价,求最小代价让所有的人都进入一个房子.每个房子只能进入一个人. 算法讨论: 注意是KM 和 ...
- HDU 1533 Going Home(KM完美匹配)
HDU 1533 Going Home 题目链接 题意:就是一个H要相应一个m,使得总曼哈顿距离最小 思路:KM完美匹配,因为是要最小.所以边权建负数来处理就可以 代码: #include <c ...
- Going Home (hdu 1533 最小费用流)
集训的图论都快结束了,我才看懂了最小费用流,惭愧啊. = = 但是今天机械键盘到了,有弄好了自行车,好高兴\(^o^)/~ 其实也不是看懂,就会套个模板而已.... 这题最重要的就是一个: 多组输入一 ...
- HDU 1533 最小费用最大流(模板)
http://acm.hdu.edu.cn/showproblem.php?pid=1533 这道题直接用了模板 题意:要构建一个二分图,家对应人,连线的权值就是最短距离,求最小费用 要注意void ...
- hdu 1533 Going Home 最小费用最大流
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533 On a grid map there are n little men and n house ...
- Going Home HDU - 1533 费用流
http://acm.hdu.edu.cn/showproblem.php?pid=1533 给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个&q ...
- HDU 1533
http://acm.hdu.edu.cn/showproblem.php?pid=1533 人和房子数量相同,每个人进房子,费用是人到房子的曼哈顿距离,求最小费用 可用最小费用最大流求解,建立虚拟的 ...
随机推荐
- mysql_sql语句之美
无线地址及数量统计 单个用户无线登录信息统计
- 从浏览器启动应用程序 - Application URL
关键字:Browser,Application,URL Protocol,Windows,Mac,IE,Chrome,Safari. OS: Windows 7, OS X Yosemite. Win ...
- 1062 Talent and Virtue (25)
/* L (>=60), the lower bound of the qualified grades -- that is, only the ones whose grades of ta ...
- hdu 5343 MZL's Circle Zhou SAM
MZL's Circle Zhou 题意:给定两个长度不超过a,b(1 <= |a|,|b| <= 90000),x为a的连续子串,b为y的连续子串(x和y均可以是空串):问x+y形成的不 ...
- Elasticsearch升级至1.x后API的变化-三
请支持原创:http://www.cnblogs.com/donlianli/p/3841762.html 1.索引格式 1.x之前的版本,被索引的文档type会同时出现在url和传输的数据格式中 ...
- 拼音操作工具类 - PinyinUtil.java
拼音操作工具类,提供字符串转换成拼音数组.汉字转换成拼音.取汉字的首字母等方法. 源码如下:(点击下载 -PinyinUtil.java.pinyin4j-2.5.0.jar ) import net ...
- JVM内存区域模型
一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代” .“非堆” ,"perm", 它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共 ...
- [js综合问题汇总]js窗口关闭事件,表单名称,父窗口子窗口,var变量名
<script type="text/javascript"> window.onbeforeunload = onbeforeunload_handler; //wi ...
- 【C++基础】sizeof 数组 指针 空NULL
笔试遇到很多sizeof的小题,博主基础堪忧,怒总结如下,还是要巩固基础啊啊啊! sizeof操作符 对象所占 栈内存空间的大小,单位是字节 关键词:char 数组 指针 结构体 class [注意 ...
- tornado做简单socket服务器(TCP)
http://blog.csdn.net/chenggong2dm/article/details/9041181 服务器端代码如下: #! /usr/bin/env python #coding=u ...