题目链接:

https://vjudge.net/problem/POJ-2195

题目大意:

给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致。man每移动一格需花费$1(即单位费用=单位距离),一间house只能入住一个man。现在要求所有的man都入住house,求最小费用。

思路:

KM算法传送门: 理解篇    运用篇

每个man和house建立带权二分图,曼哈顿距离就是边的值,这里要求最小费用,也就是二分图最小权值匹配,但是KM算法求的是二分图最大权值匹配,所以此处用边的负数求最优匹配,求出来的答案的负数就是最小权匹配。

注意:题目说house最多100,但是没有说明man的范围,所以man应该最多100*100。

应该用house为二分图的X部,因为算法复杂度和X部点数有关,所以用点数少的house为X部

因为存的是负数,在预处理X部的顶标值初始化应该是-INF,不能是0

剩下的就是模板啦

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxx = + ;//house的上限
const int maxy = + ;//man的上限
const int INF = 0x3f3f3f3f;
int cntx, cnty;//X部的点的数目,Y部点的数目
bool visx[maxx], visy[maxy];//是否加入增广路
int wx[maxx], wy[maxy];//顶标值
int cx[maxx], cy[maxy];//匹配的点
int minz;//顶标值和边权最小的差值
int Map[maxx][maxy];//保存边 bool dfs(int u)
{
visx[u] = ;
for(int v = ; v <= cnty; v++)
{
if(!visy[v])//还未加入增广路
{
int t = wx[u] + wy[v] - Map[u][v];
//计算边权和顶标之差,为0表示是相等子图
if(t == )
{
visy[v] = ;
if(cy[v] == - || dfs(cy[v]))//还未匹配或者反向找到增广路
{
cy[v] = u;
cx[u] = v;
//cout<<u<<"v"<<v<<endl;
return ;
}
}
else if(t > )minz = min(minz, t);
}
}
return ;
} int KM()
{
memset(cx, -, sizeof(cx));
memset(cy, -, sizeof(cy));
memset(wx, -INF, sizeof(wx));//注意,这里存的是负边,所以初始化必须是负无穷
memset(wy, , sizeof(wy));
for(int i = ; i <= cntx; i++)//预处理出X部的顶标值
{
for(int j = ; j <= cnty; j++)
{
wx[i] = max(wx[i], Map[i][j]);
//cout<<wx[i]<<endl;
}
}
for(int i = ; i <= cntx; i++)
{
while()
{
minz = INF;
memset(visx, , sizeof(visx));
memset(visy, , sizeof(visy));
if(dfs(i))break; for(int j = ; j <= cntx; j++)
if(visx[j])wx[j] -= minz;
for(int j = ; j <= cnty; j++)
if(visy[j])wy[j] += minz;
}
}
int ans = ;
for(int i = ; i <= cntx; i++)
if(cx[i] != -)ans += Map[i][cx[i]];
return ans;
}
struct node
{
int x, y;
node(){}
node(int x, int y):x(x), y(y){}
};
node house[maxx], man[maxy];
char M[][];
int main()
{
int n, m;
while(cin >> n >> m && (n && m))
{
cntx = cnty = ;
for(int i = ; i < n; i++)//读图
{
cin >> M[i];
for(int j = ; j < m; j++)
{
if(M[i][j] == 'H')house[++cntx] = node(i, j);
else if(M[i][j] == 'm')man[++cnty] = node(i, j);
}
} for(int i = ; i <= cntx; i++)//建图
{
for(int j = ; j <= cnty; j++)
{
Map[i][j] = -abs(house[i].x - man[j].x) - abs(house[i].y - man[j].y);
}
}
cout<<(-KM())<<endl;
}
return ;
}

POJ-2195 Going Home---KM算法求最小权值匹配(存负边)的更多相关文章

  1. poj3565 Ants km算法求最小权完美匹配,浮点权值

    /** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...

  2. 【POJ 2195】 Going Home(KM算法求最小权匹配)

    [POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

  3. hdu1533 Going Home km算法解决最小权完美匹配

    Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  4. poj 3565 uva 1411 Ants KM算法求最小权

    由于涉及到实数,一定,一定不能直接等于,一定,一定加一个误差<0.00001,坑死了…… 有两种事物,不难想到用二分图.这里涉及到一个有趣的问题,这个二分图的完美匹配的最小权值和就是答案.为啥呢 ...

  5. poj 2195 Going Home (km算法)

    题目链接: http://poj.org/problem?id=2195 解题思路: 把man和home都提取出来,然后算出每个man和home的距离算出来,然后建立匹配图,套用km算法的模板,求最小 ...

  6. POJ 3565 Ants 【最小权值匹配应用】

    传送门:http://poj.org/problem?id=3565 Ants Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: ...

  7. POJ 2195 Going Home 【二分图最小权值匹配】

    传送门:http://poj.org/problem?id=2195 Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

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

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

  9. HDU 2255 KM算法 二分图最大权值匹配

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

随机推荐

  1. 基础篇---memcache

    十分钟学会memcache,比你想象的要简单 转发:https://baijiahao.baidu.com/s?id=1588816843517136163&wfr=spider&fo ...

  2. 定时器详解和应用、js加载阻塞、css加载阻塞

    1.setTimeout().setInterval()详解和应用 1.1 详解: setTimeout.setInterval执行时机 1.2 存在问题: setInterval重复定时器可能存在的 ...

  3. 洛谷P1312 Mayan游戏

    P1312 Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他 ...

  4. Python Day23

    Django之Model操作 一.字段 字段列表 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - ...

  5. thinkphp5.1使用支付宝接口(沙箱环境)

    接口文件以及沙箱的测试账号可以去支付宝开发中心获取,下面给出一个简单地例子 我新建了一个控制器Pay用来专门做支付 <?phpnamespace app\index\controller; us ...

  6. 基于svn+ssh:访问svn的部署以及客户端配置

    1.安装ssh sudo apt-get install ssh 2.安装subversion sudo apt-get install subversion 3.为参与项目开发的成员建立用户帐户 s ...

  7. spring boot中ConditionalOnClass为什么没有classNotFound类加载异常

    查看原码时有很多飘红的地方, 这些import都失败的地方, 为什么在运行时没有报错? 首先这些@Configuration类没有被程序中的类引用到 其次即使引用到这个类,不一定引用到类中的具体某个方 ...

  8. (转)Linux硬链接、软链接及inode详解

    inode 文件储存在硬盘上,硬盘的最小存储单位叫做“扇区”(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读 ...

  9. 字符串实现Base64加密/解密

    有时候需要对字符串进行加密,不以明文显示,可以使用此方法,比如对URL的参数加密 using System; using System.Collections.Generic; using Syste ...

  10. 《C#高效编程》读书笔记08-推荐使用查询语法而不是循环

    C#语言中并不缺少控制程序流程的结构,for.while.do/while和foreach等都可以做到这一点.但我们还有更好的方式:查询语法(query syntax) 下面这段代码演示了用命令式的方 ...