標籤:tail 設定 scope == turn min 表示 如何 長度
閱讀目錄
- 二分圖部落格推薦
- 匈牙利演算法步驟
- 匈牙利演算法部落格推薦
- KM演算法步驟
- KM演算法標杆(又名頂標)的引入
- KM流程詳解
- KM演算法部落格推薦
0.二分圖二分圖的概念二分圖又稱作二部圖,是圖論中的一種特殊模型。設G=(V, E)是一個無向圖。如果頂點集V可分割為兩個互不相交的子集X和Y,並且圖中每條邊串連的兩個頂點一個在X中,另一個在Y中,則稱圖G為二分圖。可以得到線上的driver與order之間的匹配關係既是一個二分圖。二分圖的判定無向圖G為二分圖的充分必要條件是,G至少有兩個頂點,且其所有迴路的長度均為偶數。判斷無向連通圖是不是二分圖,可以使用深度優先遍曆演算法(又名交叉染色法)。下面著重介紹下交叉染色法的定義與原理首先任意取出一個頂點進行染色,和該節點相鄰的點有三種情況: 1.如果節點沒有染過色,就染上與它相反的顏色,推入隊列, 2.如果節點染過色且相反,忽視掉, 3.如果節點染過色且與父節點相同,證明不是二分圖,return
回到頂部二分圖部落格推薦代碼可參考部落格: 圖論入門———深度優先搜尋實現二分圖判定交叉染色法部落格推薦:交叉染色法判斷二分圖另外附上二分圖的性質部落格:二分圖的一些性質1.KM演算法初步KM演算法全稱是Kuhn-Munkras,是這兩個人在1957年提出的,有趣的是,匈牙利演算法是在1965年提出的。 增廣路徑增廣路徑定義:若P是圖G中一條連通兩個未匹配頂點的路徑,並且屬於M的邊和不屬於M的邊(即已匹配和待匹配的邊)在P上交替出現,則稱P為相對於M的一條增廣路徑(舉例來說,有A、B集合,增廣路由A中一個點通向B中一個點,再由B中這個點通向A中一個點……交替進行)增廣路徑有如下特性: 1. 有奇數條邊 2. 起點在二分圖的X邊,終點在二分圖的Y邊 3. 路徑上的點一定是一個在X邊,一個在Y邊,交錯出現。 4. 整條路徑上沒有重複的點 5. 起點和終點都是目前還沒有配對的點,其他的點都已經出現在匹配子圖中 6. 路徑上的所有第奇數條邊都是目前還沒有進入目前的匹配子圖的邊,而所有第偶數條邊都已經進入目前的匹配子圖。奇數邊比偶數邊多一條邊 7. 於是當我們把所有第奇數條邊都加到匹配子圖並把條偶數條邊都刪除,匹配數增加了1. 例如,藍色的是當前的匹配子圖,紅色表示未匹配的路徑,目前只有邊x0y0,然後通過x1找到了增廣路徑:x1y0->y0x0->x0y2
增廣路徑有兩種尋徑方法,一個是深搜,一個是寬搜。例如從x2出發尋找增廣路徑
- 如果是深搜,x2找到y0匹配,但發現y0已經被x1匹配了,於是就深入到x1,去為x1找新的匹配節點,結果發現x1沒有其他的匹配節點,於是匹配失敗,x2接著找y1,發現y1可以匹配,於是就找到了新的增廣路徑。
- 如果是寬搜,x1找到y0節點的時候,由於不能馬上得到一個合法的匹配,於是將它做為候選項放入隊列中,並接著找y1,由於y1已經匹配,於是匹配成功返回了。
相對來說,深搜要容易理解些,其棧可以由遞迴過程來維護,而寬搜則需要自己維護一個隊列,並對一路過來的路線自己做標記,實現起來比較麻煩。匈牙利演算法匈牙利演算法,用於求二分圖的最大匹配。何為最大匹配?假設每條邊有權值,那麼一定會存在一個最大權值的匹配情況。
回到頂部匈牙利演算法步驟演算法根據一定的規則選擇二分圖的邊加入匹配子圖中,其基本模式為:1.初始化匹配子圖為空白 2.While 找得到增廣路徑 3.Do 把增廣路徑添加到匹配子圖中
回到頂部匈牙利演算法部落格推薦KM深度優先遍曆演算法,其中附帶講解圖可參考部落格:趣寫演算法系列之–匈牙利演算法最大匹配的講解部落格:匈牙利演算法(二分圖)KM演算法KM演算法,用於求二分圖匹配的首選。何為首選?就是帶權二分圖的權值最大的完備匹配稱為首選。 那麼何為完備匹配?X部中的每一個頂點都與Y部中的一個頂點匹配,或者Y部中的每一個頂點也與X部中的一個頂點匹配,則該匹配為完備匹配。
回到頂部KM演算法步驟其演算法步驟如下:1.用鄰接矩陣(或其他方法也行啦)來儲存圖,注意:如果只是想求最大權值匹配而不要求是完全符合的話,請把各個不相連的邊的權值設定為0。2.運用貪心演算法初始化標杆。3.運用匈牙利演算法找到完備匹配。4.如果找不到,則通過修改標杆,增加一些邊。5.重複3,4的步驟,直到完全符合時可結束。
回到頂部KM演算法標杆(又名頂標)的引入二分圖首選還是二分圖匹配,所以跟和匈牙利演算法思路差不多。二分圖是特殊的網路流,首選相當於求最大(小)費用最大流,所以FF演算法(全名Ford-Fulkerson演算法)也能實現。
- 所以我們可以把這匈牙利演算法和FF演算法結合起來。這就是KM演算法的思路了:盡量找最大的邊進行連邊,如果不能則換一條較大的。
-
- FF演算法裡面,我們每次是找最長(短)路進行通流,所以二分圖匹配裡面我們也按照FF演算法找最大邊進行連邊!
- 但是遇到某個點被匹配了兩次怎麼辦?那就用匈牙利演算法變更匹配!
- 所以,根據KM演算法的思路,我們一開始要對邊權值最大的進行連線。
- 那問題就來了,我們如何讓電腦知道該點對應的權值最大的邊是哪一條?或許我們可以通過某種方式記錄邊的另一端點,但是呢,後面還要涉及改邊,又要記錄邊權值總和,而這個記錄端點方法似乎有點麻煩。
-
- 於是KM採用了一種十分巧妙的辦法(也是KM演算法思想的精髓):添加標杆(頂標)
添加標杆(頂標)流程:
- 我們對左邊每個點Xi和右邊每個點Yi添加標杆Cx和Cy。其中我們要滿足Cx+Cy>=w[x][y](w[x][y]即為點Xi、Yi之間的邊權值)
- 對於一開始的初始化,我們對於每個點分別進行如下操作:Cx=max(w[x][y]); Cy=0;
添加頂標之前的二分圖: 添加頂標之後的二分圖:
回到頂部KM流程詳解
- 初始化可行頂標的值 (設定lx,ly的初始值)
- 用匈牙利演算法尋找相等子圖的完備匹配
- 若未找到增廣路則修改可行頂標的值
- 重複(2)(3)直到找到相等子圖的完備匹配為止
使用的例子,採用匈牙利演算法進行連邊操作,將最大邊進行連線。所以原來判斷是否有邊的條件w[x][y]==0換成了 Cx+Cy==w[x][y]
- 於是乎我們連了AD,形成一個新的二分圖(我們下面叫它二分子圖好了)
- 接下來就尷尬了,電腦接下來要連B點的BD,但是D點已經和A點連了,怎麼辦呢???
-
- 根據匈牙利演算法,我們做的是將A點與其他點進行連線,但此時的子圖裡“不存在”與A點相連的其他邊,怎麼辦呢???
-
- 為此,我們就需要加上這些邊!很明顯,我們添邊,自然要加上不在子圖中邊權最大的邊,也就是和子圖裡這個邊權值差最小的邊。
-
- 於是,我們再一度引入了一變數d,d=min{Cx[i]+Cy[j]-w[i][j]},其中,在這個題目裡Cx[i]指的是A的標杆,Cy[j]是除D點(即已連點)以外的點的標杆。
-
- 隨後,對於原先存在於子圖的邊AD,我們將A的標杆Cx[i]減去d,D的標杆Cy[d]加上d。
-
- 這樣,這就保證了原先存在AD邊保留在了子圖中,並且把不在子圖的最大權值的與A點相連的邊AE添加到了子圖。
- 因為電腦判斷一條邊是否在該子圖的條件是其兩端的頂點的標杆滿足Cx+Cy==w[x][y]
-
- 對於原先的邊,我們對左端點的標杆減去了d,對右端點的標杆加上了d,所以最終的結果還是不變,仍然是w[x][y]。
- 對於我們要添加的邊,我們對於左端點減去了d,即Cx[i]=Cx[i]-d;為方便表示我們把更改後的的Cx[i]視為Cz[i],即Cz[i]=Cx[i]-d;
-
- 因為Cz[i]=Cx[i]-d;d=Cx[i]+Cy[j]-w[i][j];
- 把d代入左式可得Cz[i]=Cx[i]-(Cx[i]+Cy[j]-w[i][j]);
- 化簡得Cz[i]+Cy[j]=w[i][j];
- 滿足了要求!即添加了新的邊。
- 重複進行上述流程。(匈牙利演算法以及FF演算法的結合)
回到頂部KM演算法部落格推薦頂標內容講的很好:KM演算法鬆弛度內容講的比較好:二分圖的最佳完美匹配——KM演算法匈牙利演算法和FF演算法結合得到KM演算法講的很詳細:二分圖匹配之首選——KM演算法最佳講解部落格推薦:我對KM演算法的理解
KM演算法詳解[轉]