漫談匈牙利算法

匈牙利算法是由匈牙利數(shù)學(xué)家Edmonds于1965年提出典鸡,因而得名项阴。匈牙利算法是基于Hall定理中充分性證明的思想锌奴,它是部圖匹配最常見的算法兽狭,該算法的核心就是尋找增廣路徑鹿蜀,它是一種用增廣路徑求二分圖最大匹配的算法服球。(來(lái)自百度百科)

淺顯的講,就是尋找二部圖的最大匹配斩熊,先寫出幾個(gè)概念;

二部圖:二分圖又稱作二部圖粉渠,是圖論中的一種特殊模型分冈。 設(shè)G=(V,E)是一個(gè)無(wú)向圖雕沉,如果頂點(diǎn)V可分割為兩個(gè)互不相交的子集(A,B),并且圖中的每條邊(i去件,j)所關(guān)聯(lián)的兩個(gè)頂點(diǎn)i和j分別屬于這兩個(gè)不同的頂點(diǎn)集(i in A,j in B),則稱圖G為一個(gè)二分圖尤溜。(來(lái)自百度百科)

6B974A22-EFFB-4813-BF81-6149A037675A.png

當(dāng)子圖中沒有任何一個(gè)同時(shí)連接Xi和Yj的同一頂點(diǎn)的時(shí)候我們稱為二部圖的一個(gè)匹配,記為集合M

什么是最大匹配呢 如下圖

9C2492EA-5019-4BC5-A84D-A2856E55E603.png

當(dāng)匹配集合中的邊數(shù)達(dá)到最大的時(shí)候宫莱,這就是一個(gè)最大匹配丈攒,如上圖;

再提出幾個(gè)個(gè)概念
未覆蓋點(diǎn):就是在集合M中沒有邊連接到的點(diǎn)稱為未覆蓋點(diǎn)授霸。
完美匹配:當(dāng)M是二部圖的最大匹配且沒有未覆蓋點(diǎn)的時(shí)候肥印,則這個(gè)集合M就是二部圖的完美匹配。上圖中的匹配就是完美匹配绝葡,在符合最大匹配的同時(shí)深碱,M集合中的邊覆蓋了二部圖的所有點(diǎn)。

最后一個(gè)最關(guān)鍵的概念:增廣路徑 藏畅;
匈牙利算法的核心就是不停的尋找增廣路徑來(lái)擴(kuò)充匹配集合M敷硅,什么是增廣路經(jīng)呢功咒?(來(lái)自百度百科)

1-P的路徑長(zhǎng)度必定為奇數(shù)。
2-起點(diǎn)在左绞蹦,終點(diǎn)在右力奋。
3-路徑中的點(diǎn)左右交替出現(xiàn)。
4-只有起點(diǎn)和終點(diǎn)是未覆蓋點(diǎn)幽七,其他點(diǎn)都配對(duì)景殷。
5 -對(duì)增廣路徑編號(hào),所有奇數(shù)的邊都不在M中澡屡,偶數(shù)邊在M中猿挚。
6 -對(duì)增廣路徑取反得到的匹配比原來(lái)匹配多一個(gè)。

我們給出實(shí)例來(lái)理解驶鹉。


C33D49B0-2527-48FF-A442-762BEB630E01.png

我們尋找如上圖的最大匹配;首先M集合為空(即沒有邊在里面)绩蜻,然后開始從X1尋找增廣路,遵循2的原則我們只能在Yi中找室埋,找到Y(jié)1办绝,(X1,Y1 )這條路徑姚淆,滿足1-5的條件,取反孕蝉,將(X1,Y1 )這條路徑加入到M中腌逢。

2E79CD71-536E-4171-9156-844F956A8EF5.png

接著降淮,我們找到X2點(diǎn),遵循原則上忍,找到Y(jié)1骤肛,Y1不是未覆蓋點(diǎn),這個(gè)時(shí)候我們有兩種選擇窍蓝,一個(gè)是深度搜索腋颠,一個(gè)是廣度搜索,我們采用深度優(yōu)先吓笙,雖然Y1不是未覆蓋點(diǎn)淑玫,(X2,Y1)不是增廣路面睛,但是Y1連著X1,X1又和Y3相連土涝,我們考慮( X2,Y1,X1,Y3 )這條路徑幌墓,奇數(shù)冀泻?左右交替弹渔?起終點(diǎn)未覆蓋溯祸?奇路徑不屬于M偶路徑屬于?滿足所有增廣路條件博杖,所以這是一條增廣路徑氨鹏,然后取反压状,得到如下圖。

5213FA71-C31A-4461-9A5F-54AF59BF4B02.png

現(xiàn)在M集合中的路徑有兩條了镣丑,由于我們找到了增廣路徑莺匠,使得M中的邊數(shù)量增加十兢。所以增廣路徑是匈牙利算法的核心旱物,每找到一條增廣路徑,意味這M集合中邊的數(shù)量就會(huì)增加1单匣,當(dāng)找不到增廣路徑的時(shí)候宝穗,這個(gè)時(shí)候M中邊的數(shù)量就是我們二部圖的最大匹配數(shù)量。我們是怎樣找到這條路徑的呢鸡号,從X2開始尋找须鼎,我們先找到Y(jié)1堪藐,Y1不是未覆蓋點(diǎn)礁竞,我們考慮Y1的原有匹配點(diǎn)X1模捂,從X1開始尋找增廣路蜘矢,找到了Y3,當(dāng)X1有增廣路的時(shí)候岖食,那么加上(X1,Y1)(X2,Y1)這兩條路經(jīng)舞吭,依然滿足增廣路條件。所以基于我們上面的理解可以給出尋找增廣路的偽代碼

  while(找到Xi的關(guān)聯(lián)頂點(diǎn)Yj){
          if(頂點(diǎn)Yj不在增廣路徑上){
                將Yj加入增廣路
               if(Yj是未覆蓋點(diǎn)或者Yj的原匹配點(diǎn)Xk能找到增廣路徑){ //擴(kuò)充集合M
                      將Yj的匹配點(diǎn)改為Xi;
                      返回true
           }
      }
               返回false
}

從X2開始尋找是基于深度優(yōu)先的蔑穴,如果是基于廣度優(yōu)先呢存和?那么X2就會(huì)找到Y(jié)2衷旅。

給出C語(yǔ)言代碼


typedef struct tagMaxMatch{
    int edge[COUNT][COUNT];
    bool on_path[COUNT];
    int path[COUNT];
    int max_match;
}GRAPH_MATCH;

void outputRes(int *path){
    for (int i = 0 ; i<COUNT; i++) {
        printf("%d****%d\n",i,*(path+i));   //Yj在前 Xi在后
    }
}

void clearOnPathSign(GRAPH_MATCH *match){
    for (int j = 0 ; j < COUNT ; j++) {
        match->on_path[j] = false;
    }
   
}
//dfs算法
bool FindAugPath(GRAPH_MATCH *match , int xi){
    
    for (int yj = 0 ; yj < COUNT; yj++) {
        if ( match->edge[xi][yj] == 1 && !match->on_path[yj]) { //如果yi和xi相連且yi沒有在已經(jīng)存在的增廣路經(jīng)上
             match->on_path[yj] = true;
            if (match->path[yj] == -1 || FindAugPath(match,match->path[yj])) { // 如果是yi是一個(gè)未覆蓋點(diǎn)或者和yi相連的xk點(diǎn)能找到增廣路經(jīng)柿顶,
                  match->path[yj] = xi; //yj點(diǎn)加入路徑;
                  return true;
            }
        }
    }
    return false;
}

void Hungary_match(GRAPH_MATCH *match){
    for (int xi = 0; xi<COUNT ; xi++) {
          FindAugPath(match, xi);
          clearOnPathSign(match);
    }
    outputRes(match->path);
}

int main() {
    
    GRAPH_MATCH *graph = (GRAPH_MATCH *)malloc(sizeof(GRAPH_MATCH));
    for (int i = 0 ; i < COUNT ; i++) {
        for (int j = 0 ; j < COUNT ; j++) {
            graph->edge[i][j] = 0;
        }
    }
    graph->edge[0][1] = 1;
    graph->edge[0][0] = 1;
    graph->edge[1][1] = 1;
    graph->edge[1][2] = 1;
    graph->edge[2][1] = 1;
    graph->edge[2][0] = 1;
    graph->edge[3][2] = 1;
    
    for (int j = 0 ; j < COUNT ; j++) {
        graph->path[j] = -1;
        graph->on_path[j] = false;
    }
    
    Hungary_match(graph);
    
    
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绞佩,一起剝皮案震驚了整個(gè)濱河市猪钮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肘交,老刑警劉巖扑馁,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異复罐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)胀滚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門咽笼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)戚炫,“玉大人,你說(shuō)我怎么就攤上這事施掏⊙罨铮” “怎么了萌腿?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵毁菱,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我峦筒,道長(zhǎng)窗慎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任峦失,我火速辦了婚禮尉辑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘较屿。我一直安慰自己卓练,他們只是感情好襟企,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布整吆。 她就那樣靜靜地躺著辉川,像睡著了一般。 火紅的嫁衣襯著肌膚如雪府蛇。 梳的紋絲不亂的頭發(fā)上屿愚,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天妆距,我揣著相機(jī)與錄音,去河邊找鬼娱据。 笑死,一個(gè)胖子當(dāng)著我的面吹牛忌穿,可吹牛的內(nèi)容都是我干的结啼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼朴译,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼眠寿!你這毒婦竟也來(lái)了红选?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤迹辐,失蹤者是張志新(化名)和其女友劉穎甚侣,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體印荔,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡详羡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年实柠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片草则。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡炕横,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出份殿,到底是詐尸還是另有隱情塔鳍,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站掌唾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏糯彬。R本人自食惡果不足惜葱她,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一吨些、第九天 我趴在偏房一處隱蔽的房頂上張望炒辉。 院中可真熱鬧泉手,春花似錦、人聲如沸缝裤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)搀崭。三九已至猾编,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間答倡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工获茬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恕曲,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓佩谣,卻偏偏與公主長(zhǎng)得像茸俭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子调鬓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

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

  • (轉(zhuǎn)自http://www.douban.com/group/topic/14820131/腾窝,轉(zhuǎn)自人大論壇) 調(diào)整...
    f382b3d9bdb3閱讀 10,588評(píng)論 0 8
  • 來(lái)源: http://www.douban.com/group/topic/14820131/ 調(diào)整變量格式: f...
    MC1229閱讀 6,924評(píng)論 0 5
  • 題目?jī)?nèi)容 鏈接: POJ3041 算法詳解 二分圖相關(guān)知識(shí) wiki百科已經(jīng)寫得挺詳細(xì)了驴娃,主要講一下二分圖求最大匹...
    玩毛線的毛線閱讀 1,054評(píng)論 0 0
  • 轉(zhuǎn)載請(qǐng)聲明 原文鏈接 關(guān)注公眾號(hào)獲取更多資訊 這篇文章主要總結(jié)H5的一些新增的功能以及一些基礎(chǔ)歸納托慨,這里只是一個(gè)提...
    程序員poetry閱讀 9,074評(píng)論 22 225
  • 1暇榴、前言 學(xué)習(xí)是一個(gè)痛苦的過(guò)程,讓我們養(yǎng)成了不求甚解的習(xí)慣蔼紧。 2、匈牙利算法 嗯彬犯,首先網(wǎng)上已經(jīng)有很多啦。但是我覺得...
    bplusb閱讀 872評(píng)論 2 2