匈牙利 算法
一. 算法簡介
匈牙利算法是由匈牙利數學家Edmonds於1965年提出。該算法的核心就是尋找增廣路徑,它是一種用增廣路徑求二分圖最大匹配的算法。
二分圖的定義:
設G=(V,E)是一個無向圖,頂點集V可分割為兩個互不相交的子集V1,V2,那么稱此圖G為二分圖。
例如,下圖就是一個二分圖:
二分圖的匹配:
二分圖中的子圖中,每個節點只連一條邊,則稱該子圖是二分圖中的一個匹配。
極大匹配:
無法再向二分圖中加入邊,使得滿足匹配條件。
最大匹配:
所有極大匹配中邊數最多的一個匹配。
完美匹配:
如果一個圖的某個匹配中,所有的頂點都是匹配點,那么它就是一個完美匹配。
方法:
求最大匹配的一種顯而易見的算法是:先找出全部匹配,然后保留匹配數最多的。但是這個算法的時間復雜度為邊數的指數級。因此,需要尋求一種更加高效的算法。下面介紹用增廣路求最大匹配的方法。
算法圖解:
下圖是一個二分圖,現在求最大匹配。
先從1出發,找增廣路,找到1->A 這條路,標記並記錄。
從2出發,找到2->B這條路,標記並記錄。
從3開始找,發現3所連接邊全部被占用,這時進行一個神奇的操作:
從三開始找一條增廣路,3 -> A -> 1 -> B -> 2 -> C
這時,在圖中將有兩種顏色的邊刪去,留下綠色的邊。
這時,這張圖的最大匹配值就是3.
三.算法模板
核心代碼:
1 bool Hungary ( int x ) { 2 for ( int i = head[ x ] ; i ; i = E[ i ] . next ) { 3 if ( vis[ i ] ) continue ; 4 int temp = E[ i ] . to ; 5 vis[ i ] = true ; 6 if ( !match[ temp ] || Hungary ( match[ temp ] ) ) { 7 match [ temp ] = x ; 8 return true ; 9 } 10 } 11 return false ; 12 }
主程序:
for ( k=1 ; k<=M ; ++k ) { memset ( vis , false , sizeof ( vis ) ) ; if ( !Hungary ( k ) ) break ; }
時間復雜度:
鄰接矩陣:
O(n3)
鄰接表: O(nm)
鄰接表: O(nm)
空間復雜度:
鄰接矩陣:
O(n2)
鄰接表:O(n+m)
鄰接表:O(n+m)
2016-09-16 02:18:44
(完)