KM算法入門

萌萌的講解
以下為部分摘取
  最大二分匹配:在一個(gè)二分圖中找到P->q的一個(gè)匹配方案,使得匹配中的邊數(shù)量不小于任何其他的匹配。
  完備二分匹配:在一個(gè)二分圖中找到p->q的一個(gè)匹配方案,使得p中所有點(diǎn)出現(xiàn)在該匹配中。
  二分圖的帶權(quán)匹配:求出一個(gè)匹配集合,使得集合中邊的權(quán)值之和最大或最小。
  二分圖的最優(yōu)匹配:為完備匹配,在此基礎(chǔ)上,才要求匹配的邊權(quán)值之和最大或最小。二分圖的帶權(quán)匹配與最優(yōu)匹配不等價(jià),也不互相包含。

KM算法實(shí)現(xiàn)求二分圖的最優(yōu)匹配。KM算法可以實(shí)現(xiàn)為O(N^3)。
[KM算法的幾種轉(zhuǎn)化]
  • KM算法是求最大權(quán)完備匹配,如果要求最小權(quán)完備匹配怎么辦?方法很簡(jiǎn)單,只需將所有的邊權(quán)值取其相反數(shù),求最大權(quán)完備匹配,匹配的值再取相反數(shù)即可。
  • KM算法的運(yùn)行要求是必須存在一個(gè)完備匹配,如果求一個(gè)最大權(quán)匹配(不一定完備)該如何辦?依然很簡(jiǎn)單,把不存在的邊權(quán)值賦為0。
  • KM算法求得的最大權(quán)匹配是邊權(quán)值和最大,如果我想要邊權(quán)之積最大,又怎樣轉(zhuǎn)化?還是不難辦到,每條邊權(quán)取自然對(duì)數(shù),然后求最大和權(quán)匹配,求得的結(jié)果a再算出e^a就是最大積匹配。至于精度問題則沒有更好的辦法了。

KM算法的鄰接矩陣模板:

const int MAXN = 210;
const int INF = 0x3f3f3f3f;

int love[MAXN][MAXN];   // 記錄每個(gè)妹子和每個(gè)男生的好感度
int ex_girl[MAXN];      // 每個(gè)妹子的期望值
int ex_boy[MAXN];       // 每個(gè)男生的期望值
bool vis_girl[MAXN];    // 記錄每一輪匹配匹配過的女生
bool vis_boy[MAXN];     // 記錄每一輪匹配匹配過的男生
int match[MAXN];        // 記錄每個(gè)男生匹配到的妹子 如果沒有則為-1
int slack[MAXN];        // 記錄每個(gè)漢子如果能被妹子傾心最少還需要多少期望值

int n,m;
bool dfs(int girl)
{
    vis_girl[girl] = true;

    for (int boy = 0; boy < m; ++boy) {

        if (vis_boy[boy]) continue; // 每一輪匹配 每個(gè)男生只嘗試一次

        int gap = ex_girl[girl] + ex_boy[boy] - love[girl][boy];

        if (gap == 0) {  // 如果符合要求
            vis_boy[boy] = true;
            if (match[boy] == -1 || dfs( match[boy] )) {    // 找到一個(gè)沒有匹配的男生 或者該男生的妹子可以找到其他人
                match[boy] = girl;
                return true;
            }
        } else {
            slack[boy] = min(slack[boy], gap);  // slack 可以理解為該男生要得到女生的傾心 還需多少期望值 取最小值 備胎的樣子【捂臉
        }
    }

    return false;
}

int KM()
{
    memset(match, -1, sizeof match);    // 初始每個(gè)男生都沒有匹配的女生
    memset(ex_boy, 0, sizeof ex_boy);   // 初始每個(gè)男生的期望值為0

    // 每個(gè)女生的初始期望值是與她相連的男生最大的好感度
    for (int i = 0; i < n; ++i) {
        ex_girl[i] = love[i][0];
        for (int j = 1; j < m; ++j) {
            ex_girl[i] = max(ex_girl[i], love[i][j]);
        }
    }

    // 嘗試為每一個(gè)女生解決歸宿問題
    for (int i = 0; i < n; ++i) {

        fill(slack, slack + m, INF);    // 因?yàn)橐∽钚≈?初始化為無窮大

        while (1) {
            // 為每個(gè)女生解決歸宿問題的方法是 :如果找不到就降低期望值,直到找到為止

            // 記錄每輪匹配中男生女生是否被嘗試匹配過
            memset(vis_girl, false, sizeof vis_girl);
            memset(vis_boy, false, sizeof vis_boy);

            if (dfs(i)) break;  // 找到歸宿 退出

            // 如果不能找到 就降低期望值
            // 最小可降低的期望值
            int d = INF;
            for (int j = 0; j < m; ++j)
                if (!vis_boy[j]) d = min(d, slack[j]);
            if(d==INF) return -1;  //無法松弛,找不到完備匹配
            for (int j = 0; j < n; ++j) {
                // 所有訪問過的女生降低期望值
                if (vis_girl[j]) ex_girl[j] -= d;
            }

            for (int j = 0; j < m; ++j) {
                // 所有訪問過的男生增加期望值
                if (vis_boy[j]) ex_boy[j] += d;
                // 沒有訪問過的boy 因?yàn)間irl們的期望值降低,距離得到女生傾心又進(jìn)了一步!
                else slack[j] -= d;
            }
        }
    }

    // 防止匹配到不存在的邊
    int res = 0,flag=0;
    for(int i = 0; i < m; i++){
        if(match[i]==-1||love[match[i]][i]==-INF)
            continue;
        res += love[match[i]][i];
        flag++;
    }
    if(flag<n) res=-1;
    return res;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • G - Cyclic Tour題意:圖中有n個(gè)點(diǎn)和m條有向邊現(xiàn)在要將該圖分成若干環(huán),每個(gè)環(huán)中至少有兩個(gè)點(diǎn)。環(huán)與環(huán)不...
    Gitfan閱讀 852評(píng)論 0 1
  • 1、前言 學(xué)習(xí)是一個(gè)痛苦的過程,讓我們養(yǎng)成了不求甚解的習(xí)慣。 2、匈牙利算法 嗯,首先網(wǎng)上已經(jīng)有很多啦。但是我覺得...
    bplusb閱讀 922評(píng)論 2 2
  • 1 序 2016年6月25日夜,帝都,天下著大雨,拖著行李箱和同學(xué)在校門口照了最后一張合照,搬離寢室打車去了提前租...
    RichardJieChen閱讀 5,397評(píng)論 0 12
  • 某天逛淘寶,偶然間發(fā)現(xiàn)了一些美麗的布料。于是,一個(gè)新的愛好又出現(xiàn)了…… 第一次接觸布藝這種東西,特別好奇,又不確定...
    錦時(shí)96閱讀 524評(píng)論 6 6
  • 文/雷欽程 我,一個(gè)今年升四年級(jí)的小學(xué)生,心里是滿滿的期待。我有一大堆問題...
    花信兒閱讀 699評(píng)論 0 0

友情鏈接更多精彩內(nèi)容