POJ 2195 Going Home(最小权匹配、KM算法)
来源:互联网 发布:js 中文 unicode 编辑:程序博客网 时间:2024/06/04 23:20
题目链接:
POJ 2195 Going Home
题意:
给出一个r*c的矩阵,字母H代表房屋,字母m代表客人,房屋的数量和客人的数量相同。每间房只能住一个人。求这些客人全部住进客房的最少移动步数?
#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <string>#include <climits>#include <queue>#include <map>#include <set>#include <iostream>using namespace std;const int MAX_N = 400;//求最大(小)权匹配时图的级别一般为10^2,所以用邻接矩阵存图int r, c, n, m;char s[MAX_N][MAX_N];int match[MAX_N], visx[MAX_N], visy[MAX_N], lx[MAX_N], ly[MAX_N], w[MAX_N][MAX_N], slack[MAX_N];struct Pos{ int x,y;}house[MAX_N*MAX_N],host[MAX_N*MAX_N];inline bool dfs(int x){ visx[x] = 1; for(int y = 0; y < m; y++){ if(visy[y]) continue; int tmp = lx[x] + ly[y] - w[x][y]; if( tmp == 0 ){ visy[y] = 1; if(match[y] == -1 || dfs(match[y])){ match[y] = x; return true; //找到增广轨 } }else { slack[y] = min(slack[y], tmp); } } return false; //没有找到增广轨,说明顶点X没有对应的匹配, //与完备匹配(相等子图的3完备匹配)不符}inline int KM(){ memset(match, -1, sizeof(match)); memset(ly, 0, sizeof(ly)); for(int i = 0; i < n; i++){ lx[i] = INT_MIN; for(int j = 0; j < m; j++){ lx[i] = max(lx[i], w[i][j]); } } for(int i = 0; i < n; i++){ //初始边的松弛值为最大 for(int j = 0; j < m; j++){ slack[j] = INT_MAX; } while(1){ memset(visx, 0, sizeof(visx)); memset(visy, 0, sizeof(visy)); if(dfs(i)) break; //找到增广轨,则该点增广完成,进入下一点增广 //没有找到增广轨需要改变顶标使图中可行边数量增加 int d = INT_MAX; for(int j = 0; j < m; j++){ if( !visy[j] ) d = min(d, slack[j]); } //增广轨(增广过程中遍历到)中X方顶标全部减去常数d for(int j = 0; j < n; j++) { if(visx[j]) lx[j] -= d; } //增广轨中Y方顶标全部增加d for(int j = 0; j < m; j++) { if(visy[j]) ly[j] += d; else slack[j] -= d; //不在增广轨中的顶点Y } } } int res = 0; for(int j = 0; j < m; j++) { if( match[j] != -1) res += w[match[j]][j]; } return res;}int main(){ while(~scanf("%d%d",&r, &c) && (r || c)){ n = m = 0; for(int i = 0; i < r; i++) { scanf("%s",s[i]); for(int j = 0; j < c; j++){ if(s[i][j] == 'H'){ house[n].x = i; house[n++].y = j; }else if(s[i][j] == 'm') { host[m].x = i; host[m++].y = j; } } } for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ int tmp = abs(house[i].x - host[j].x) + abs(house[i].y - host[j].y); w[i][j] = -tmp; //求最小权匹配,将边权取反,然后求最大权匹配 } } int ans = KM(); printf("%d\n",-ans); //结果取相反数 } return 0;}
0 0
- POJ 2195 Going Home(最小权匹配、KM算法)
- 【POJ 2195】 Going Home(KM算法求最小权匹配)
- POJ 2195 Going Home(KM算法——二分图最小权匹配)
- poj 2195 Going Home 二分图最小权匹配KM算法
- POJ 2195&&HDU 1533 Going Home(KM算法解决二分图最小权匹配)
- POJ 2195】 Going Home KM算法求最小权匹配模板
- POJ - 2195 Going Home (构图 最大匹配KM算法)
- KM算法 最优匹配(最大权匹配) hdu 2255 奔小康赚大钱 最小权匹配 poj 2195 Going Home
- POJ-2195 Going Home (最小费用最大流初学 && 最大权二分匹配—KM算法)
- poj 2195 Going Home(二分图最优匹配KM算法)
- hdu 1533 Going Home(最小权匹配KM)
- hdu 1533 Going Home(KM 最小权值匹配)
- [ACM] HDU 1533 Going Home (二分图最小权匹配,KM算法)
- POJ 2195-Going Home(KM算法/最小费用最大流算法)
- POJ 2195 Going Home (二分图最大权匹配、KM算法)
- poj 2195 Going Home km算法
- HDU 1533Going Home(KM算法求二分图最小权匹配或者最小费用最大流)
- POJ 2195 Going Home(KM)
- spring框架的引入
- 51单片机与Arduino通过nrf24l01无线模块通信
- LeetCode-150.Evaluate Reverse Polish Notation
- emWin 2天速成实例教程000_如何快速入门ucGUI/emWin
- 文章标题
- POJ 2195 Going Home(最小权匹配、KM算法)
- The Donkey of Gui Zhou驴和老虎是否相遇问题(hdu4704)
- java容器
- Zabbix3.0 自动邮件报障
- leetcode 171 Excel Sheet Column Number C++
- <canvas>学习笔记——实时绘制线条摆动
- Java泛型
- Unity3d中的属性(Attributes)整理
- 用栈实现两位数表达式的求值