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 人和房子数量相同,每个人进房子,费用是人到房子的曼哈顿距离,求最小费用 可用最小费用最大流求解,建立虚拟的 ...
随机推荐
- SSH-KEY服务及批量分发与管理实战
SSH服务 一.SSH服务介绍 SSH是Secure Shell Protocol的简写,由IETF网络工作小组制定:在进行数据传输之前,SSH先对联机数据包通过加密技术进行加密处理,加密后再进行数据 ...
- SQL动态更新表字段 传入字段可能为空
小技巧: 项目组有修改产品的基本信息字段 但有时候传入的字段可能为空 也可能不为空 动态修改表中字段. USE [BetaProductMarket_DB] GO )) BEGIN DROP PRO ...
- (转)Qt Model/View 学习笔记 (六)——在views中选择数据项
在views中选择数据项 概念 用于新的view类中的选择模型比Qt3中的模型有了很大的改进.它为基于model/view架构的选择提供了更为全面的描述.尽管对提供了的views来说,负责操纵选择的标 ...
- 外部表查询时出现ORA-29913和ORA-29400错误
create table t_ext_tab(id char(1),name char(6)) organization external( type oracle_loader default di ...
- make问题:make[1] entering directory
执行make distclean命令.
- [译] ASP.NET 生命周期 – ASP.NET 请求生命周期(二)
ASP.NET 请求生命周期 全局应用类也可以用来跟踪每个独立请求的生命周期,包括请求从 ASP.NET 平台传递到 MVC 框架.ASP.NET 框架会创建一个定义在 Global.asax 文件中 ...
- 用Canvas制作小游戏——贪吃蛇
今天呢,主要和小伙伴们分享一下一个贪吃蛇游戏从构思到实现的过程~因为我不是很喜欢直接PO代码,所以只copy代码的童鞋们请出门左转不谢. 按理说canvas与其应用是老生常谈了,可我在准备阶段却搜索不 ...
- 操作邮箱的类和文件的Md5【粘】
MailMessage mailMsg = new MailMessage();//两个类,别混了,要引入System.Net这个Assembly mailMsg.From ...
- Qt的gzip模块实现
一直没找到Qt中方便的gzip模块,于是自己动手,调用zlib模块实现了一份. 目标: 1.gzip的压缩与解压 2.内存中操作 3.方便的Qt接口 实现分析: gzip 压缩算法为 defla ...
- Android Studio 单刷《第一行代码》系列目录
前言(Prologue) 本系列将使用 Android Studio 将<第一行代码>(书中讲解案例使用Eclipse)刷一遍,旨在为想入坑 Android 开发,并选择 Android ...