匈牙利和KM算法

匈牙利算法和KM算法

这两天学了匈牙利算法和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;
            }
        }
}

猜你喜欢

转载自blog.csdn.net/Two_Punch/article/details/81676427
今日推荐