就是最基本的二分图最优匹配,将每个人向每个房子建一条边,权值就是他们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. hadoop streaming 编程

    概况 Hadoop Streaming 是一个工具, 代替编写Java的实现类,而利用可执行程序来完成map-reduce过程.一个最简单的程序 $HADOOP_HOME/bin/hadoop jar ...

  2. 分析nginx access log日志的命令

    统计访问最多的ip 1. tail -n 10000 xxaccess_log | cut -d " " -f 1 |sort|uniq -c|sort -rn|head -10 ...

  3. F - Coins

    F - Coins Time Limit:3000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Submit St ...

  4. Linux设置禁止用户登陆

    Linux设置禁止用户登陆 vim /etc/shadow 第二栏(密码栏)设为*,会丢失密码 usermod -L username # -L Lock; -U Unlock chsh userna ...

  5. tomcat中的webapps

    使用IDE方便开发,使用文本编辑器建立Web工程,有助于理解工程的各个文件组成及底层原理.需搭建好服务器(常用tomcat),当然需要Java运行环境了. 一.建立JSP文件,如helloworld. ...

  6. 简单http笔记

    https是以安全为目的的网络传输协议,可以认为是http的安全版,https使用ssl协议保证安全传输.https位于网络模型的应用层,使用默认端口443进行通信,URL以https开头是https ...

  7. Velocity中#set指令

    引用可以让模板设计者生成动态内容,而指令允许设计者真正的负责页面的展现和内容. 指令是以#开头,后面紧跟一个关键字,比如if,else,foreach等.而这个关键字,是可以被放在{}中间的.这是规范 ...

  8. c# Internet时间服务器同步

    2009-02-02 17:48 8226人阅读 评论(2) 收藏 举报 服务器internetc#socketstringwindows 需要用到的名空间 using System.Net; usi ...

  9. php 基本符号

    用这么久了,竟然PHP的基本符号都没有认全,看到@号还查了半天才知道什么意思.把基本符号列表帖一下吧,需要的朋友可以参考~ 注解符号:          // 单行注解              /* ...

  10. nginx 的安装

    一.必要软件准备1.安装pcre 为了支持rewrite功能,我们需要安装pcre 复制代码代码如下: # yum install pcre* //如过你已经装了,请跳过这一步 2.安装openssl ...