就是最基本的二分图最优匹配,将每个人向每个房子建一条边,权值就是他们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. php-fpm 启动不了 libiconv.so.2找不到

    service php-fpm start  Starting php-fpm /alidata/server/php/sbin/php-fpm: error while loading shared ...

  2. HDU 5441 Travel (并查集+数学+计数)

    题意:给你一个带权的无向图,然后q(q≤5000)次询问,问有多少对城市(城市对(u,v)与(v,u)算不同的城市对,而且u≠v)之间的边的长度不超过d(如果城市u到城市v途经城市w, 那么需要城市u ...

  3. WebView自适应并嵌套在ScrollView里

    大致思路:通过流的形式把网页抓取下来,然后对webView进行设置. 1.对webView进行设置 web.setWebViewClient(new WebViewClient() { @Overri ...

  4. copy and Xcopy 复制文件到另一地址

    1. copy不能复制文件夹下的文件,而Xcopy可以. 2. Xcopy不能连接文件,而copy可以连接文件 eg : 将A盘中的A.TXT和B.TXT文件连接起来,连接后的文件名为C.TXT    ...

  5. TC srm 673 300 div1

    TC srm.673 300 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 Description 给你n(n<=50)匹马和n个人,一匹马和一个人能 ...

  6. HDU 4348 To the moon 可持久化线段树,有时间戳的区间更新,区间求和

    To the moonTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.a ...

  7. 通过ulimit改善linux系统性能(摘自IBM)

    本文介绍了 ulimit 内键指令的主要功能以及用于改善系统性能的 ulimit 用法.通过这篇文章,读者不仅能够了解 ulimit 所起的作用.而且能够学会怎样更好地通过 ulimit 限制资源的使 ...

  8. ValueBar

    https://github.com/PhilJay/ValueBar

  9. [AngularJS] ui-router: named views

    The ui-router library for AngularJS provides the ability to name views within your application. This ...

  10. Java内部类的自我理解

    本文借鉴网络上多位大牛的博客和文章.感谢各位不知名人士的分享. 一.什么事内部类? 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的成员,而且依附于外部类而存在的.内部类能够为静态,可用p ...