题意:

  一个矩阵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 (最小费用流)的更多相关文章

  1. hdu 1533 Going Home 最小费用流

    构建地图非常easy bfs预处理地图.距离的成本 来源所有m建方,流程1费0 m所有H建方,流程1距离成本 H汇点建设成为各方.流程1费0 #include<cstdio> #inclu ...

  2. 【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, ...

  3. POJ 2195 Going Home / HDU 1533(最小费用最大流模板)

    题目大意: 有一个最大是100 * 100 的网格图,上面有 s 个 房子和人,人每移动一个格子花费1的代价,求最小代价让所有的人都进入一个房子.每个房子只能进入一个人. 算法讨论: 注意是KM 和 ...

  4. HDU 1533 Going Home(KM完美匹配)

    HDU 1533 Going Home 题目链接 题意:就是一个H要相应一个m,使得总曼哈顿距离最小 思路:KM完美匹配,因为是要最小.所以边权建负数来处理就可以 代码: #include <c ...

  5. Going Home (hdu 1533 最小费用流)

    集训的图论都快结束了,我才看懂了最小费用流,惭愧啊. = = 但是今天机械键盘到了,有弄好了自行车,好高兴\(^o^)/~ 其实也不是看懂,就会套个模板而已.... 这题最重要的就是一个: 多组输入一 ...

  6. HDU 1533 最小费用最大流(模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 这道题直接用了模板 题意:要构建一个二分图,家对应人,连线的权值就是最短距离,求最小费用 要注意void ...

  7. 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 ...

  8. Going Home HDU - 1533 费用流

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 给一个网格图,每两个点之间的匹配花费为其曼哈顿距离,问给每个的"$m$"匹配到一个&q ...

  9. HDU 1533

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 人和房子数量相同,每个人进房子,费用是人到房子的曼哈顿距离,求最小费用 可用最小费用最大流求解,建立虚拟的 ...

随机推荐

  1. 数据可视化(一)-Matplotlib简易入门

    本节的内容来源:https://www.dataquest.io/mission/10/plotting-basics 本节的数据来源:https://archive.ics.uci.edu/ml/d ...

  2. 《C和指针》 读书笔记 -- 第14章 预处理器

    1.相邻字符串常量被自动链接为一个字符串:"my""name"="myname" 2.##把位于两边的符号连接成一个符号: #define ...

  3. container_of宏定义分析---linux内核

    问题:如何通过结构中的某个变量获取结构本身的指针??? 关于container_of宏定义在[include/linux/kernel.h]中:/*_** container_of - cast a ...

  4. CentOS安装,更新Python

    1.查看当前Python版本 python -V 2.查看当前CentOS版本 cat /etc/redhat-release 3.安装所有的开发工具包 yum groupinstall " ...

  5. C语言-创建链表及排序

    #include <stdio.h> #define NEWNODE (Node *)malloc(sizeof(Node)) typedef struct mynode{ int num ...

  6. MySQL的alter的使用

    ALTER TABLE 语句用于在已有的表中添加.修改或删除列 1.ADD [COLUMN] column name (column definitions) [FIRST or AFTER colu ...

  7. mac使用wget下载网站(仿站)

    wget -c -r -np -k -L -p http://www.xxxx.com 参考 wget的安装 http://blog.csdn.net/ssihc0/article/details/7 ...

  8. 【BZOJ 1927】 [Sdoi2010]星际竞速

    Description 10 年一度的银河系赛车大赛又要开始了.作为全银河最盛大的活动之一, 夺得这个项目的冠军无疑是很多人的梦想,来自杰森座 α星的悠悠也是其中之一. 赛车大赛的赛场由 N 颗行星和 ...

  9. Increase SharePoint Execution Timeout

    <system.web> <compilation batch="false" batchTimeout="600" maxBatchSize ...

  10. Solr + Hadoop = Big Data Love

    FROM:http://architects.dzone.com/articles/solr-hadoop-big-data-love 许多人使用Hadoop的开源项目来处理大数据的大数据集,因为它是 ...