KM算法入門

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

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

KM算法的鄰接矩陣模板:

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

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

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

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

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

        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] )) {    // 找到一個沒有匹配的男生 或者該男生的妹子可以找到其他人
                match[boy] = girl;
                return true;
            }
        } else {
            slack[boy] = min(slack[boy], gap);  // slack 可以理解為該男生要得到女生的傾心 還需多少期望值 取最小值 備胎的樣子【捂臉
        }
    }

    return false;
}

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

    // 每個女生的初始期望值是與她相連的男生最大的好感度
    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]);
        }
    }

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

        fill(slack, slack + m, INF);    // 因為要取最小值 初始化為無窮大

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

            // 記錄每輪匹配中男生女生是否被嘗試匹配過
            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 因為girl們的期望值降低衣吠,距離得到女生傾心又進(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)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市缚俏,隨后出現(xiàn)的幾起案子惊搏,更是在濱河造成了極大的恐慌,老刑警劉巖忧换,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恬惯,死亡現(xiàn)場離奇詭異,居然都是意外死亡亚茬,警方通過查閱死者的電腦和手機(jī)酪耳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刹缝,“玉大人碗暗,你說我怎么就攤上這事∩液唬” “怎么了言疗?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長颂砸。 經(jīng)常有香客問我洲守,道長疑务,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任梗醇,我火速辦了婚禮知允,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘叙谨。我一直安慰自己温鸽,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布手负。 她就那樣靜靜地躺著涤垫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪竟终。 梳的紋絲不亂的頭發(fā)上蝠猬,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機(jī)與錄音统捶,去河邊找鬼榆芦。 笑死,一個胖子當(dāng)著我的面吹牛喘鸟,可吹牛的內(nèi)容都是我干的匆绣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼什黑,長吁一口氣:“原來是場噩夢啊……” “哼崎淳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起愕把,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤拣凹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后恨豁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咐鹤,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年圣絮,在試婚紗的時候發(fā)現(xiàn)自己被綠了祈惶。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡扮匠,死狀恐怖捧请,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情棒搜,我是刑警寧澤疹蛉,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站力麸,受9級特大地震影響可款,放射性物質(zhì)發(fā)生泄漏育韩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一闺鲸、第九天 我趴在偏房一處隱蔽的房頂上張望筋讨。 院中可真熱鬧,春花似錦摸恍、人聲如沸悉罕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壁袄。三九已至,卻和暖如春媚媒,著一層夾襖步出監(jiān)牢的瞬間嗜逻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工缭召, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留栈顷,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓恼琼,卻偏偏與公主長得像妨蛹,于是被迫代替她去往敵國和親屏富。 傳聞我的和親對象是個殘疾皇子晴竞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容

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