题目链接:

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. Linux之shell备份数据库

    功能概述: 使用shell脚本对服务器的数据库(全部或指定数据库)进行备份.对15天(固定天数)之前的数据库备份进行删除 命令实现: 待定

  2. IDEA的git密码修改

    问题: 如果你办公的电脑是同事用过,在每次提交git的时候都显示是他的名字.想要修改提交git用户名密码. 但是博客idea 修改Git密码和账号方法所示方法无效.且操作系统是win10.(其他操作系 ...

  3. 安装篇:MySQL系列之一

    环境:CentOS6.9系统安装MariaDB-10.2.15 一.yum包管理器安装MariaDB-server ​ 1)配置yum源(MariaDB官方源) [root@centos6 ~]# v ...

  4. [Leetcode]012. Integer to Roman

    public class Solution { public String intToRoman(int num) { String M[] = {"", "M" ...

  5. Luogu P5103 「JOI 2016 Final」断层 树状数组or线段树+脑子

    太神仙了这题... 原来的地面上升,可以倒着操作(时光倒流),转化为地面沉降,最后的答案就是每个点的深度. 下面的1,2操作均定义为向下沉降(与原题意的变换相反): 首先这个题目只会操作前缀和后缀,并 ...

  6. APP请求超时问题-ios超时-android超时

    最近发现公司的app在高峰期超时严重.用wifi网络一直超时,但qq等却正常.换成手机卡网络正常. 起初以为是DNS解析问题. 后来抓包,发现DNS解析正常,可以得到正确的A记录. 但tcp retr ...

  7. USB转串口连接线与串口调试助手的使用

    ---作者吴疆,未经允许,严禁转载,违权必究--- ---欢迎指正,需要源码和文件可站内私信联系--- -----------点击此处链接至博客园原文----------- 功能说明:宇泰UT-890 ...

  8. 敏捷开发(Agile development)

    敏捷开发(Agile development) 敏捷开发是一种以人为核心.迭代.循序渐进的开发方法.在敏捷开发中,软件项目的构建被切分成多个子项目,各个子项目的成果都经过测试,具备集成和可运行的特征. ...

  9. MySQL分库分表的技巧

    分表是分散数据库压力的好方法. 分表,最直白的意思,就是将一个表结构分为多个表,然后,可以再同一个库里,也可以放到不同的库. 当然,首先要知道什么情况下,才需要分表.个人觉得单表记录条数达到百万到千万 ...

  10. JAVA中数组介绍

    一.数组: 数组指一组数据的集合,数组中的每个数据被称作元素. 二.数组定义: 数组类型[] 数组名 = new 数组类型[元素个数或数组长度]: (注意:等号前面的[]里面不能写任何东西) 也可以以 ...