匈牙利算法和KM算法
这两天学了匈牙利算法和KM算法,全部都是网上找大神们的博客学的 先通过一些图了解KM算法到底是什么情况,但是要搞清楚KM算法又不得不提到匈牙利算法,要 想搞清楚匈牙利算法又不得不搞清楚二分图是个什么玩意儿,这是一个我们熟悉的递归啊~ |
二分图是个什么东西,要想搞清楚,不得不看图,我从这位高手的博客有了个了解 |
二分图附图讲解
有了感性的认识后,还是要对概念搞清楚,啥子最大匹配、最小边覆盖、最小点覆盖、 最有匹配。。。 |
二分图及相关概念
然后就是匈牙利算法,还是先来有图的一目了然,先不管三七二十一,不管为啥子有这个算法, 这个算法有啥子用,这个算法为啥子要这样设计。。。。先搞清楚这个算法的流程再说,这位仁 兄非常幽默通俗的讲解了 |
趣味匈牙利
其实他说的那个 “ 腾 ” 我感觉应该就是增广路径的本质,就是 “ 腾 ” 除了位置,才好找 到最大匹配,也说清楚了匈牙利算法的本质 |
然后就是KM算法,还是老规矩,先看有图的讲解
KM算法入门
看了过后虽然有了个大概的认识,但还是昏的,然后我就配合这两篇还有代码 |
KM算法
KM算法理解
const int N = 20, inf = 2147483647;
int w[N][N], linky[N], visx[N], visy[N], lack;
int lx[N] = {0}, ly[N] = {0}; //顶标
bool find(int x) {
visx[x] = true;
for (int y = 0; y < N; ++y) {
if (visy[y]) continue;
int t = lx[x] + ly[y] - w[x][y];
if (!t) {
visy[y] = true;
if (!~linky[y] || find(linky[y])) {
linky[y] = x;
return true;
}
} else lack = min(lack, t);
}
return false;
}
void km() {
memset(linky, -1, sizeof(linky));
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
lx[i] = max(lx[i], w[i][j]); //初始化顶标
for (int x = 0; x < N; ++x)
for (; ;) {
memset(visx, 0, sizeof(visx));
memset(visy, 0, sizeof(visy));
lack = inf;
if (find(x)) break;
for (int i = 0; i < N; ++i) {
if (visx[i]) lx[i] -= lack;
if (visy[i]) ly[i] += lack;
}
}
}