POJ-2195 Going Home---KM算法求最小权值匹配(存负边)
题目链接:
https://vjudge.net/problem/POJ-2195
题目大意:
给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致。man每移动一格需花费$1(即单位费用=单位距离),一间house只能入住一个man。现在要求所有的man都入住house,求最小费用。
思路:
每个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算法求最小权值匹配(存负边)的更多相关文章
- poj3565 Ants km算法求最小权完美匹配,浮点权值
/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...
- 【POJ 2195】 Going Home(KM算法求最小权匹配)
[POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submiss ...
- hdu1533 Going Home km算法解决最小权完美匹配
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- poj 3565 uva 1411 Ants KM算法求最小权
由于涉及到实数,一定,一定不能直接等于,一定,一定加一个误差<0.00001,坑死了…… 有两种事物,不难想到用二分图.这里涉及到一个有趣的问题,这个二分图的完美匹配的最小权值和就是答案.为啥呢 ...
- poj 2195 Going Home (km算法)
题目链接: http://poj.org/problem?id=2195 解题思路: 把man和home都提取出来,然后算出每个man和home的距离算出来,然后建立匹配图,套用km算法的模板,求最小 ...
- POJ 3565 Ants 【最小权值匹配应用】
传送门:http://poj.org/problem?id=3565 Ants Time Limit: 5000MS Memory Limit: 65536K Total Submissions: ...
- POJ 2195 Going Home 【二分图最小权值匹配】
传送门:http://poj.org/problem?id=2195 Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submis ...
- 运动员最佳匹配问题 KM算法:带权二分图匹配
题面: 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势:Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势. ...
- HDU 2255 KM算法 二分图最大权值匹配
奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
随机推荐
- C++的STL总结(1)
没有很系统的学过算法,c++也只是学些基础,虽然经常会用一些STL里面的函数,但是并没有对STL模板库有一个清晰的了解,趁着寒假有时间就自己在网上百度浏览别人的总结的内容,自己汇集并总结了一下,希望对 ...
- express+vue-cli实现前后端分离交互小例
准备工作 1.Express 应用生成器 npm install express-generator -g 2.vue-cli手脚架 npm install -g vue-cli 3.项目结构 . ├ ...
- Codeforces 92C【二分】
意: 求最少需要几个s1串拼接存在子串s2 (1≤|s1|≤1e4,1≤|s2|≤1e6). 思路(感谢ZQC): 每个字母的出现位置存个vector. 假设你当前已经用了A串的前x个字符,现在想要匹 ...
- FFT求卷积(多项式乘法)
FFT求卷积(多项式乘法) 卷积 如果有两个无限序列a和b,那么它们卷积的结果是:\(y_n=\sum_{i=-\infty}^\infty a_ib_{n-i}\).如果a和b是有限序列,a最低的项 ...
- bzoj 3123: [Sdoi2013]森林(45分暴力)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4184 Solved: 1235[Submit][Status ...
- JAVA String.format()的使用
常规类型的格式化 String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.熟悉C语言的同学应该记得C语言的sprintf()方法,两者有类似之处.format()方法有两种重 ...
- 我的省选 Day -10
Day -10 今天的分数也许会比昨天更低.. 感觉2017年比远古时代的2007年的第一试难诶. 估个分数好了,我猜88分(为什么猜了一个这么吉利的数字??到时候出来没几分就啪啪啪打脸了) 和昨天一 ...
- oracle基本命令
1.首先,创建(新)用户: create user username identified by password; username:新用户名的用户名 password: 新用户的密码也可以不创建新 ...
- bzoj5506:[gzoi2019]旅行者
传送门 正反两边dijkstra染色,然后枚举一下边,求出最小值就好啦 代码: #include<cstdio> #include<iostream> #include< ...
- Poj 2096 (dp求期望 入门)
/ dp求期望的题. 题意:一个软件有s个子系统,会产生n种bug. 某人一天发现一个bug,这个bug属于某种bug,发生在某个子系统中. 求找到所有的n种bug,且每个子系统都找到bug,这样所要 ...