给个地图有人和房子

保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价

问让人都住在房子里最小代价


显然是个带权二分图最大匹配

转化成以一个网络,规定w是容量,c是代价

1.S向人连边,w=1,c=0

2.房子向T连边,w=1,c=0

3.人向房子连边 w=1,c=距离

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#define N 10000
#define INF 1000000000
using namespace std;
deque <int> q;
int head[N],lev[N],dist[N],n,m,ecnt=1,vis[N],S,T,ans,H,M;
char mp[110][110];
struct adj
{
int nxt,v,w,c;
}e[200*200];
int Abs(int x)
{return x>0?x:-x;}
struct coor
{
int x,y;
int operator - (const coor &a)const
{return Abs(x-a.x)+Abs(y-a.y);}
};
coor make(int x,int y)
{
coor ret;
ret.x=x,ret.y=y;
return ret;
}
vector <coor> house,man;
inline void add(int u,int v,int w,int c)
{
e[++ecnt].v=v,e[ecnt].w=w,e[ecnt].c=c,e[ecnt].nxt=head[u],head[u]=ecnt;
e[++ecnt].v=u,e[ecnt].w=0,e[ecnt].c=-c,e[ecnt].nxt=head[v],head[v]=ecnt;
}
inline int spfa(int s,int t)
{
int v;
memset(vis,0,sizeof(vis));
for (int i=s;i<=t;i++) dist[i]=INF;
dist[t]=0,vis[t]=1;
q.push_back(t);
while (!q.empty())
{
int u=q.front();q.pop_front();
for (int i=head[u];i;i=e[i].nxt)
if (e[i^1].w>0 && dist[v=e[i].v]>dist[u]-e[i].c)
{
dist[v]=dist[u]-e[i].c;
if (!vis[v])
{
vis[v]=1;
if (!q.empty() && dist[v]<dist[q.front()])
q.push_front(v);
else
q.push_back(v);
}
}
vis[u]=0;
}
return dist[s]<INF;
}
inline int dfs(int x,int flow)
{
if (x==T)
return vis[T]=1,flow;
int used=0,tmp,v;
vis[x]=1;
for (int i=head[x];i;i=e[i].nxt)
if (!vis[v=e[i].v] && e[i].w>0 && dist[x]-e[i].c==dist[v])
{
tmp=dfs(v,min(e[i].w,flow-used));
if (tmp>0)
ans+=tmp*e[i].c,e[i].w-=tmp,e[i^1].w+=tmp,used+=tmp;
if (used==flow) break;
}
return used;
}
inline int CostFlow()
{
int Flow=0;
while (spfa(S,T))
{
vis[T]=1;
while (vis[T])
{
memset(vis,0,sizeof(vis));
Flow+=dfs(S,INF);
}
}
return Flow;
}
void init()
{
memset(head,0,sizeof(head));
man.clear();
house.clear();
ans=M=H=0;
ecnt=1;
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n==0 && m==0) break;
init();
for (int i=1;i<=n;i++)
scanf("%s",mp[i]+1);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (mp[i][j]=='m')
man.push_back(make(i,j)),M++;
else if (mp[i][j]=='H')
house.push_back(make(i,j)),H++;
T=H+M+1;
for (int i=0;i<M;i++)
for (int j=0;j<H;j++)
add(i+1,M+j+1,1,man[i]-house[j]);
for (int i=1;i<=M;i++)
add(S,i,1,0);
for (int i=1;i<=H;i++)
add(M+i,T,1,0);
CostFlow();
printf("%d\n",ans);
} return 0;
}

POJ 2195 Going Home | 带权二分图匹配的更多相关文章

  1. POJ 2195 Going Home (带权二分图匹配)

    POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...

  2. 运动员最佳匹配问题 KM算法:带权二分图匹配

    题面: 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势:Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势. ...

  3. 费用流模板(带权二分图匹配)——hdu1533

    /* 带权二分图匹配 用费用流求,增加源点s 和 汇点t */ #include<bits/stdc++.h> using namespace std; #define maxn 1000 ...

  4. hdu5045:带权二分图匹配

    题目大意 : n个人 做m道题,其中 每连续的n道必须由不同的人做 已知第i人做出第j题的概率为pij,求最大期望 思路:考虑每连续的n道题 都要n个人来做,显然想到了带权的二分图匹配 然后就是套模板 ...

  5. Glorious Brilliance (最短路 + 带权二分图匹配)

    这是一道代码大题.一开始读错题意了,然后理解成直接看上去的那种相邻,然后想不通好久!!! 把不同联通的图分离出来,然后先预处理一下形成之后的相邻图的状态,然后根据01确定哪一些是需要更换状态的,然后建 ...

  6. [NOI2012]美食节——费用流(带权二分图匹配)+动态加边

    题目描述 小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜品.当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师.然后每个厨师就会同时开始 ...

  7. [HAOI2008]移动玩具(状压&带权二分图)

    题目描述 • 一个 4 × 4 的 0/1 矩阵 • 每次可以交换相邻两个元素 • 求从初始状态到目标状态的最小交换次数 输入格式 前四行,每行一个长为 4 的 0/1 字符串,描述初始状态. 后四行 ...

  8. Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配)

    Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配) Description 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的 ...

  9. KM(Kuhn-Munkres)算法求带权二分图的最佳匹配

    KM(Kuhn-Munkres)算法求带权二分图的最佳匹配 相关概念 这个算法个人觉得一开始时有点难以理解它的一些概念,特别是新定义出来的,因为不知道是干嘛用的.但是,在了解了算法的执行过程和原理后, ...

随机推荐

  1. Fetch 头像剪切修改

    前言:通过Input file upload 图片到canvas 中进行剪裁,react 可以引入react-avatar-editor对图片进行剪裁 react-avatar-editor的使用 & ...

  2. JDK1.8简单配置环境变量---两步曲

    鄙人最近重新装完系统之后,在安装和配置jdk1.8的时候,发现网上许多教程配置jdk环境变量时都还在沿用传统的方式配置,但是随着技术的更新,完全没有必要那么麻烦了. 下载和安装jdk的教程,在这里就不 ...

  3. 交换机基础配置之结合以太通道的vlan设置

    我们将以上面的拓扑图来做实验,建立以太通道,并设置好vlan,将pc1和pc3放在同一vlan,将pc2和pc4放在同一vlan,同一vlan能跨交换机通信 在一切还没布置之前,四台pc机都在同一网段 ...

  4. float 浮动详解

    浮动(float):浮动原先设定时主要是用于文本环绕图像设定的,后来发现其在css布局中有很大的帮助,故渐渐使用浮动. 浮动后的元素脱离了文档的普通流,使得浮动的元素不占据文档的位置,其他元素可以覆盖 ...

  5. 【Effective C++ 读书笔记】条款02: 尽量以 const, enum, inline 替换 #define

    条款02: 尽量以 const, enum, inline 替换 #define 这个条款或许可以改为“宁可以编译器替换预处理器”. 编译过程: .c文件--预处理-->.i文件--编译--&g ...

  6. java多线程批量读取文件(七)

    新公司入职一个多月了,至今没有事情可以做,十来个新同事都一样抓狂,所以大家都自己学习一些新东西,我最近在看zookeeper,感觉蛮不错的,和微服务的zuul以及eureka功能类似,只是代码复杂了一 ...

  7. git的使用入门

    写作目的: 快速的上手git版本控制+github神器进行基本的版本同步操作. 怎么做? 对于任意一个代码项目,使用git_bash进入到代码目录 如果没有进行过初始化操作:应当使用git init  ...

  8. 笔记-selenium+chrome headless

    笔记-selenium+chrome headless 1.      selenium+chrome headless phantomjs与selenium分手了,建议使用其它无头浏览器. chro ...

  9. Smail 中的一些点

    smali中所有操作都需要经过寄存器, 本地寄存器以v开头, 参数寄存器以p开头, 非static方法中p0是this 没有-object后缀的操作指令表示操作的对象是基本类型 invoke-dire ...

  10. Android通过用代码画虚线椭圆边框背景来学习一下shape的用法

    在Android程序开发中,我们经常会去用到Shape这个东西去定义各种各样的形状,shape可以绘制矩形环形以及椭圆,所以只需要用椭圆即可,在使用的时候将控件比如imageview或textview ...