就是最基本的二分图最优匹配,将每个人向每个房子建一条边,权值就是他们manhattan距离。然后对所有权值取反,求一次最大二分图最优匹配,在将结果取反就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Maxn 110
using namespace std;
int n;//点的数目
int lx[Maxn],ly[Maxn]; //顶点标号
int weight[Maxn][Maxn];// 边的权值
int slack[Maxn];// Y(i)的松弛函数
int sx[Maxn],sy[Maxn]; //标记X,Y中的顶点是否在交错路径上
int match[Maxn];//Y的匹配
struct Point{
int x,y;
}house[Maxn],man[Maxn];
int Dis(Point a,Point b)
{
return abs(a.x-b.x)+abs(a.y-b.y);
}
int dfs(int u)
{
sx[u]=;
int i;
for(i=;i<=n;i++)
{
if(!sy[i]&&lx[u]+ly[i]==weight[u][i])//如果在相等子图中,且未被访问
{
sy[i]=;
if(match[i]==-||dfs(match[i]))
{
match[i]=u;
return ;
}
}
else
if(!sy[i])//Y(i)不在交错路径当中
slack[i]=min(slack[i],lx[u]+ly[i]-weight[u][i]);
}
return ;
}
int bestmatch(bool f)
{
int i,j;
if(!f)
{
for(i=;i<=n;i++)
{
lx[i]=-0x7FFFFFFF;
ly[i]=;
for(j=;j<=n;j++)
{
weight[i][j]=-weight[i][j];
lx[i]=max(lx[i],weight[i][j]);
}
}
}
else
{
for(i=;i<=n;i++)
{
lx[i]=;
ly[i]=;
for(j=;j<=n;j++)
lx[i]=max(lx[i],weight[i][j]);
}
}
memset(match,-,sizeof(match));
for(i=;i<=n;i++)
while()
{
memset(sx,,sizeof(sx));
memset(sy,,sizeof(sy));
for(j=;j<=Maxn-;j++)
slack[j]=0x7FFFFFFF;
if(dfs(i))
break;
int dx=0x7FFFFFFF;
for(j=;j<=n;j++)
dx=min(dx,slack[j]);
for(j=;j<=n;j++)
{
if(sx[j])
lx[j]-=dx;
if(sy[j])
ly[j]+=dx;
}
}
int ans=;
for(i=;i<=n;i++)
ans+=weight[match[i]][i];
if(!f)
ans=-ans;
return ans;
}
int main()
{
int i,j,N,M,a,b;
char str[];
while(scanf("%d%d",&N,&M),N||M)
{
a=b=;
for(i=;i<=N;i++)
{
scanf("%s",&str);
for(j=;j<M;j++)
{
if(str[j]=='H')
house[++a].x=i,house[a].y=j;
if(str[j]=='m')
man[++b].x=i,man[b].y=j;
}
}
n=a;
for(i=;i<=n;i++)
{
for(j=;j<=n;j++)
weight[i][j]=Dis(man[i],house[j]);
}
printf("%d\n",bestmatch(false));
}
return ;
}

最小费油最大流解法:

#include<iostream>
#include<cstring>
#include<cstring>
using namespace std;
const int size = ;
const int INF = 0x7fffffff;
struct Point{
int x,y;
};
struct Edge
{
int to;
int vol;
int cost;
int next;
}e[size*];
Point house[],man[];
int index[size];
int edgeNum;
int pre[size], pos[size];
int dis[size], que[size*];
bool vis[size];
void insert(int from, int to, int vol, int cost)
{
e[edgeNum].to = to;
e[edgeNum].vol = vol;
e[edgeNum].cost = cost;
e[edgeNum].next = index[from];
index[from] = edgeNum++;
e[edgeNum].to = from;
e[edgeNum].vol = ;
e[edgeNum].cost = -cost;
e[edgeNum].next = index[to];
index[to] = edgeNum++;
}
int DIS(Point p1,Point p2)
{
return abs(p1.x-p2.x)+abs(p1.y-p2.y);
}
bool spfa(int s, int t)
{
int i;
memset(pre, -, sizeof(pre));
memset(vis, , sizeof(vis));
int head, tail; head = tail = ;
for(i = ; i < size; i++)
dis[i] = INF;
que[tail++] = s;
pre[s] = s;
dis[s] = ;
vis[s] = ;
while(head != tail)
{ int now = que[head++];
vis[now] = ;
for(i = index[now]; i != -; i = e[i].next)
{
int adj = e[i].to;
if(e[i].vol > && dis[now] + e[i].cost < dis[adj])
{
dis[adj] = dis[now] + e[i].cost;
pre[adj] = now;
pos[adj] = i;
if(!vis[adj])
{
vis[adj] = ;
que[tail++] = adj;
}
}
}
}
return pre[t] != -;
}
int MinCostFlow(int s, int t, int flow)
{
int i;
int cost = ;
flow = ;
while(spfa(s, t))
{
int f = INF;
for(i = t; i != s; i = pre[i])
if (e[pos[i]].vol < f) f = e[pos[i]].vol;
flow += f; cost += dis[t] * f;
for(i = t; i != s; i = pre[i])
{
e[pos[i]].vol -= f;
e[pos[i] ^ ].vol += f;
}
}
return cost; // flow是最大流值
}
int main()
{
int n,m,i,j,u,v;
char c;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==&&m==)
break;
memset(index,-,sizeof(index));
int k1=,k2=;
for(i=;i<=n;i++)
{
for(j=;j<=m;j++)
{
cin>>c;
switch(c)
{
case '.':break;
case 'm':man[++k1].x=i,man[k1].y=j;break;
case 'H':house[++k2].x=i,house[k2].y=j;break;
}
}
}
for(i=;i<=k1;i++)
{ for(j=;j<=k2;j++)
{
insert(i,j+k1,,DIS(man[i],house[j]));
}
insert(,i,,);
insert(i+k1,k1+k2+,,);
}
//spfa(0,k1+k2+1);
int ans=MinCostFlow(,k1+k2+,);
printf("%d\n",ans);
}
return ;
}

poj 2195 二分图最优匹配 或 最小费用最大流的更多相关文章

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

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

  2. POJ 2135 Farm Tour (网络流,最小费用最大流)

    POJ 2135 Farm Tour (网络流,最小费用最大流) Description When FJ's friends visit him on the farm, he likes to sh ...

  3. POJ2195 Going Home —— 最大权匹配 or 最小费用最大流

    题目链接:https://vjudge.net/problem/POJ-2195 Going Home Time Limit: 1000MS   Memory Limit: 65536K Total ...

  4. POJ 3686:The Windy's(最小费用最大流)***

    http://poj.org/problem?id=3686 题意:给出n个玩具和m个工厂,每个工厂加工每个玩具有一个时间,问要加工完这n个玩具最少需要等待的平均时间.例如加工1号玩具时间为t1,加工 ...

  5. POJ 3422 Kaka's Matrix Travels 【最小费用最大流】

    题意: 卡卡有一个矩阵,从左上角走到右下角,卡卡每次只能向右或者向下.矩阵里边都是不超过1000的正整数,卡卡走过的元素会变成0,问卡卡可以走k次,问卡卡最多能积累多少和. 思路: 最小费用最大流的题 ...

  6. poj 3565 二分图最优匹配

    思路: 将ant与tree之间用距离来做权值,求最小权匹配就可以了.可以想到,如果有两条线段相交,那么将这两个线段交换一个顶点,使其不相交,其权值和一定会更小. 就像斜边永远比直角边长一样的道理. # ...

  7. POJ 3422 Kaka's Matrix Travels(最小费用最大流)

    http://poj.org/problem?id=3422 题意 : 给你一个N*N的方格,每个格子有一个数字,让你从左上角开始走,只能往下往右走,走过的数字变为0,走K次,问最大能是多大,累加的. ...

  8. poj 2195 二分图带权匹配+最小费用最大流

    题意:有一个矩阵,某些格有人,某些格有房子,每个人可以上下左右移动,问给每个人进一个房子,所有人需要走的距离之和最小是多少. 貌似以前见过很多这样类似的题,都不会,现在知道是用KM算法做了 KM算法目 ...

  9. POJ 2195:Going Home(最小费用最大流)

    http://poj.org/problem?id=2195 题意:有一个地图里面有N个人和N个家,每走一格的花费是1,问让这N个人分别到这N个家的最小花费是多少. 思路:通过这个题目学了最小费用最大 ...

随机推荐

  1. 在Android4.0中Contacts拨号盘界面剖析(源码)

      通过在 ViewPager 的适配器对象中,发现过一下三行代码 private DialpadFragment mDialpadFragment; private CallLogFragment ...

  2. Algorithms Part 1-Question 6- 2SUM Median-数和以及中位数问题

    本次有两个编程问题,一个是求两个数的和满足一定值的数目,另一个是求中位数. 2SUM问题 问题描述 The goal of this problem is to implement a variant ...

  3. Connection对象连接加密2

    一般情况下,大多数人习惯于将数据库连接写在web.config上里面,理论上讲,将明文存放在该文件里面是安全的,因为web.config文件是不允许被客户端下载,但一旦该文件泄漏出去,哪怕是很短的时间 ...

  4. jeewx的使用_02 解析微信服务器post过来的数据

    如果在微信公众号接入了第三方的URL,那么用户微信服务器的请求将会被推送到第三方的URL上面,那么该如何解析数据呢?下面来分析 找到MessageUtil.java 这个类中有一个parseXml的静 ...

  5. Node.js和mybatis分别实现mysql中like变量模糊查询

    <!-- mybatis --> <where> <if test="varName != '' and varName != null" > ...

  6. UVa10562 Undraw the Trees

      注意点: 空树情况处理. >= && buf[r+][i-]=='-') i--; #include<cstdio> #include<cstring> ...

  7. 80端口被NT kernel & System 占用pid 4

    前段时间停止了Apache,结果在打开的时候发现无法打开,80端口被占用,于是win+r 运行cmd 输入netstat -ano 可以看到80端口被PID4占用,于是打开任务管理器-进程-查看,选择 ...

  8. Codeforces Gym 100286G Giant Screen 水题

    Problem G.Giant ScreenTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/con ...

  9. Oracle使用goldengate分别向Oracle和mysql双路的单向复制

    一.Oracle分别向Oracle和mysql双路的单向复制是在: ORACLE-mysql的单向复制基础上做的.http://blog.csdn.net/q947817003/article/det ...

  10. ListView 文件重命名

          unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Control ...