poj2195最小权值二分匹配KM算法
2015-11-05 21:43
218 查看
poj2195KM算法
== 我只是自己看看的 ==具体要看km是怎么弄的请看此链接:
这是我觉得网络上将的最让我懂的
/content/2633357.html
然后普通的KM是n4,这题要用n3的才能过,n4我超时
这题只要构图正确,弄出二维矩阵,直接扔到模板上就出结果了
代码部分
我给下输入的构图代码char s[MAXN]; int i, j, res; while (scanf("%d%d", &n, &m) && (n + m)) { H = M = res = 0; for (i = 0; i < n; i++) { scanf("%s", s); for (j = 0; j < m; j++) { if (s[j] == 'H') house[H].r = i, house[H++].c = j; else if (s[j] == 'm') man[M].r = i, man[M++].c = j; } } for (i = 0; i < M; i++) //求最小带权匹配可以将权值改为负数 { for (j = 0; j < H; j++) { map[i][j] = abs(man[i].r - house[j].r) + abs(man[i].c - house[j].c); } }
KM的代码
/* * KM算法,求最大或最小权二分匹配,用二维矩阵完成 */ int map[MAXN][MAXN];//二维矩阵权值 int A[MAXN];//A的标记值 int B[MAXN];//B的标记值 bool visA[MAXN]; bool visB[MAXN]; int match[MAXN];//匹配的点 int slack[MAXN]; bool find_path(int i)//找路径 { visA[i] = true; for (int j = 0; j < H; j++) { if (!visB[j] && A[i] + B[j] == map[i][j]) { visB[j] = true; if (match[j] == -1 || find_path(match[j])) { match[j] = i; return true; } } else if (A[i] + B[j] > map[i][j]) //j属于B,且不在交错路径中 slack[j] = min(slack[j], A[i] + B[j] - map[i][j]); } return false; } void KM(int num)//true求最大权,false求最小权,num要匹配的对数 { int i, j, d; memset(A, 0, sizeof(A)); memset(B, 0, sizeof(B)); memset(match, -1, sizeof(match)); for (i = 0; i < num; i++) { for (j = 0; j < num; j++) { A[i] = max(map[i][j], A[i]); } } for (i = 0; i < num; i++) { for (j = 0; j < num; j++) slack[j] = inf; while (1) { memset(visA, 0, sizeof(visA)); memset(visB, 0, sizeof(visB)); if (find_path(i)) break; //返回true退出,从i点出发找到交错路径则跳出循环 for (d = inf, j = 0; j < num; j++) //取最小的slack[j] { if (!visB[j] && d > slack[j]) d = slack[j]; } for (j = 0; j < num; j++) //集合A中位于交错路径上的-d { if (visA[j]) A[j] -= d; } for (j = 0; j < num; j++) //集合B中位于交错路径上的+d { if (visB[j]) B[j] += d; else slack[j] -= d; //注意修改不在交错路径上的slack[j] } } } } int Kuhn_Munkras(bool maxweight, int num) { if (!maxweight) { //如果求最小匹配,则要将边权取反 for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { map[i][j] = -map[i][j]; } } } KM(num); int sum = 0; for (int i = 0; i < num; i++) { if (match[i] >= 0) { sum += map[match[i]][i]; } } if (!maxweight) sum = -sum; return sum; }
相关文章推荐
- 让左边对象集合中的元素执行同一个方法
- tcp长连接和保活时间
- MySQL数据库性能优化之缓存参数优化
- SDUT 3340 树的同构
- spring文件
- Android开发&send email
- 35 个 jQuery 小技巧
- 筛选法求素数
- POJ 3237 Tree(树链剖分——边权)
- vi编辑器的基本使用方法
- 查看linux系统下网卡是否连接网线的状态
- 联接
- HTML框架<Frame>用法
- 让框架的高度自适应
- (微博)光通信技术
- zoj 1051 A New Growth Industry
- 二分法查找某数
- Android第三方服务(1):语音识别(1)
- 3.Swift的常量与变量
- 单线程02