pku 2195 Going Home KM最小权匹配问题
2012-07-21 20:58
260 查看
http://poj.org/problem?id=2195
在一个n*m的方格里有nx人(m)和ny个房子(H),(nx = ny)人每次可以向四周移动单位距离,花费1¥,求最小花费是每个人都能进入一个房间。
最小费用最大流可以做/article/7104890.html
这里是个二分图求最小权匹配问题,可以用KM算法求,只要把w[i][j] 化成负数,太用木板求最大的负数,然后输出-KM()就得到最小的整数了。
在一个n*m的方格里有nx人(m)和ny个房子(H),(nx = ny)人每次可以向四周移动单位距离,花费1¥,求最小花费是每个人都能进入一个房间。
最小费用最大流可以做/article/7104890.html
这里是个二分图求最小权匹配问题,可以用KM算法求,只要把w[i][j] 化成负数,太用木板求最大的负数,然后输出-KM()就得到最小的整数了。
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #define maxn 102 using namespace std; struct node { int x,y; }p[maxn*50],h[maxn*50]; const int inf = 99999999; int w[maxn][maxn],link[maxn]; int lx[maxn],ly[maxn];//记录顶标 int slack[maxn]; bool vtx[maxn],vty[maxn];//记录X,Y点集是否被访问过 int nx,ny,n,m; char str[maxn][maxn]; bool dfs(int i) { int j; vtx[i] = true; for (j = 0; j < ny; ++j) { if (vty[j]) continue; int tmp = lx[i] + ly[j] - w[i][j]; if (tmp == 0) { vty[j] = true; if (link[j] == -1 || dfs(link[j])) { link[j] = i; return true; } } else slack[j] = min(tmp,slack[j]); } return false; } int KM() { int i,j; for (i = 0; i < nx; ++i) { for (j = 0,lx[i] = -inf; j < ny; ++j) { lx[i] = max(lx[i],w[i][j]); } } for (i = 0; i < maxn; ++i) { link[i] = -1; ly[i] = 0; } for (i = 0; i < nx; ++i) { for (j = 0; j < ny; ++j) slack[j] = inf; while (1) { for (j = 0; j < maxn; ++j) vtx[j] = vty[j] = false; if (dfs(i)) break; int d = inf; for (j = 0; j < ny; ++j) { if (!vty[j] && d > slack[j]) d = slack[j]; } if (d == inf) return -1; for (j = 0; j < nx; ++j) if (vtx[j]) lx[j] -= d; for (j = 0; j < ny; ++j) if (vty[j]) ly[j] += d; else slack[j] -= d; } } int sum = 0; for (i = 0; i < ny; ++i) { if (link[i] > -1) sum += w[link[i]][i]; } return sum; } int main() { int i,j; while (~scanf("%d%d",&n,&m)) { if (!n && !m) break; nx = ny = 0; for (i = 0; i < n; ++i) { scanf("%s",str[i]); for (j = 0; j < m; ++j) { if (str[i][j] == 'm') { p[nx].x = i; p[nx++].y = j; } else if (str[i][j] == 'H') { h[ny].x = i; h[ny++].y = j; } } } for (i = 0; i < nx; ++i) { for (j = 0; j < ny; ++j) { w[i][j] = -inf; } } for (i = 0; i < nx; ++i) { for (j = 0; j < ny; ++j) { w[i][j] = -(abs(p[i].x - h[j].x) + abs(p[i].y - h[j].y)); } } printf("%d\n",-KM()); } return 0; }
相关文章推荐
- poj 2195(KM求最小权匹配)
- pku 2195 KM算法求最小权二分匹配
- poj 2195(KM求最小权匹配)
- 二分图完备匹配(最小费用 || KM) poj 2195 GoingHome
- POJ 2195 Going Home / HDU 1533(最小费用最大流模板)
- pku2195二分图的最佳匹配问题mub
- 关于二分图的最大匹配(最小点覆盖)问题的资料整理
- poj2195 Going Home 最小权值匹配
- hdu 1853 Cyclic Tour(KM 最小权值匹配)
- poj2195_KM最小权值和
- POJ 2195 Going Home(最小权匹配、KM算法)
- 正则-贪婪匹配(最大匹配) 和最小匹配的问题。
- 【POJ 2400】 Supervisor, Supervisee(KM求最小权匹配)
- poj 3686 The Windy's 二分图最小权和匹配KM
- HDU1533Going Home(KM匹配之最小值匹配)
- POJ 2195 二分图最小权匹配KM算法
- HDU 3488 Tour 用费用流解决完美匹配最小费用问题
- pku 2195 Going Home 最小费最大流问题
- Going Home POJ - 2195 最小费用最大流
- POJ 3686 —— 最小费用流||最小费用匹配&KM