日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

二分匹配详解

發布時間:2023/11/27 生活经验 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二分匹配详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

????二分圖又稱作二部圖,是圖論中的一種特殊模型。 設G=(V,E)是一個無向圖,如果頂點V可分割為兩個互不相交的子集(A,B),并且圖中的每條邊(i,j)所關聯的兩個頂點i和j分別屬于這兩個不同的頂點集(i in A,j in B),則稱圖G為一個二分圖。

二分圖的最大匹配:

匈牙利算法?

完美匹配: 如果所有點都在匹配邊上,稱這個最大匹配是完美匹配。?

最小覆蓋: 最小覆蓋要求用最少的點(X集合或Y集合的都行)讓每條邊都至少和其中一個點關聯。可以證明:最少的點(即覆蓋數)=最大匹配數

最小路徑覆蓋:?
用盡量少的不相交簡單路徑覆蓋有向無環圖G的所有結點。解決此類問題可以建立一個二分圖模型。把所有頂點i拆成兩個:X結點集中的i和Y結點集中的i',如果有邊i->j,則在二分圖中引入邊i->j',設二分圖最大匹配為m,則結果就是n-m。

最大獨立集問題:?
在N個點的圖G中選出m個點,使這m個點兩兩之間沒有邊.求m最大值.?
如果圖G滿足二分圖條件,則可以用二分圖匹配來做.最大獨立集點數 = N - 最大匹配數?

二分圖最大匹配問題的匈牙利算法:?

分圖的最大匹配有兩種求法,第一種是最大流(我在此假設讀者已有網絡流的知識);第二種就是我現在要講的匈牙利算法。這個算法說白了就是最大流的算法,但是它跟據二分圖匹配這個問題的特點,把最大流算法做了簡化,提高了效率。
最大流算法的核心問題就是找增廣路徑(augment path)。匈牙利算法也不例外,它的基本模式就是:

初始時最大匹配為空
while 找得到增廣路徑
??? do 把增廣路徑加入到最大匹配中去

可見和最大流算法是一樣的。但是這里的增廣路徑就有它一定的特殊性,下面我來分析一下。
(注:匈牙利算法雖然根本上是最大流算法,但是它不需要建網絡模型,所以圖中不再需要源點和匯點,僅僅是一個二分圖。每條邊也不需要有方向。)


圖1是我給出的二分圖中的一個匹配:[1,5]和[2,6]。圖2就是在這個匹配的基礎上找到的一條增廣路徑:3->6->2->5->1->4。我們借由它來描述一下二分圖中的增廣路徑的性質:

(1)有奇數條邊。
(2)起點在二分圖的左半邊,終點在右半邊。
(3)路徑上的點一定是一個在左半邊,一個在右半邊,交替出現。(其實二分圖的性質就決定了這一點,因為二分圖同一邊的點之間沒有邊相連,不要忘記哦。)
(4)整條路徑上沒有重復的點。
(5)起點和終點都是目前還沒有配對的點,而其它所有點都是已經配好對的。(如圖1、圖2所示,[1,5]和[2,6]在圖1中是兩對已經配好對的點;而起點3和終點4目前還沒有與其它點配對。)
(6)路徑上的所有第奇數條邊都不在原匹配中,所有第偶數條邊都出現在原匹配中。(如圖1、圖2所示,原有的匹配是[1,5]和[2,6],這兩條配匹的邊在圖2給出的增廣路徑中分邊是第2和第4條邊。而增廣路徑的第1、3、5條邊都沒有出現在圖1給出的匹配中。)
(7)最后,也是最重要的一條,把增廣路徑上的所有第奇數條邊加入到原匹配中去,并把增廣路徑中的所有第偶數條邊從原匹配中刪除(這個操作稱為增廣路徑的取反),則新的匹配數就比原匹配數增加了1個。(如圖2所示,新的匹配就是所有藍色的邊,而所有紅色的邊則從原匹配中刪除。則新的匹配數為3。)

不難想通,在最初始時,還沒有任何匹配時,圖1中的兩條灰色的邊本身也是增廣路徑。因此在這張二分圖中尋找最大配匹的過程可能如下:

(1)找到增廣路徑1->5,把它取反,則匹配數增加到1。
(2)找到增廣路徑2->6,把它取反,則匹配數增加到2。
(3)找到增廣路徑3->6->2->5->1->4,把它取反,則匹配數增加到3。
(4)再也找不到增廣路徑,結束。

當然,這只是一種可能的流程。也可能有別的找增廣路徑的順序,或者找到不同的增廣路徑,最終的匹配方案也可能不一樣。但是最大匹配數一定都是相同的。

對于增廣路徑還可以用一個遞歸的方法來描述。這個描述不一定最準確,但是它揭示了尋找增廣路徑的一般方法:
“從點A出發的增廣路徑”一定首先連向一個在原匹配中沒有與點A配對的點B。如果點B在原匹配中沒有與任何點配對,則它就是這條增廣路徑的終點;反之,如果點B已與點C配對,那么這條增廣路徑就是從A到B,再從B到C,再加上“從點C出發的增廣路徑”。并且,這條從C出發的增廣路徑中不能與前半部分的增廣路徑有重復的點。
比如圖2中,我們要尋找一條從3出發的增廣路徑,要做以下3步:
(1)首先從3出發,它能連到的點只有6,而6在圖1中已經與2配對,所以目前的增廣路徑就是3->6->2再加上從2出發的增廣路徑。
(2)從2出發,它能連到的不與前半部分路徑重復的點只有5,而且5確實在原匹配中沒有與2配對。所以從2連到5。但5在圖1中已經與1配對,所以目前的增廣路徑為3->6->2->5->1再加上從1出發的增廣路徑。
(3)從1出發,能連到的不與自已配對并且不與前半部分路徑重復的點只有4。因為4在圖1中沒有與任何點配對,所以它就是終點。所以最終的增廣路徑是3->6->2->5->1->4。

但是嚴格地說,以上過程中從2出發的增廣路徑(2->5->1->4)和從1出發的增廣路徑(1->4)并不是真正的增廣路徑。因為它們不符合前面講過的增廣路徑的第5條性質,它們的起點都是已經配過對的點。我們在這里稱它們為“增廣路徑”只是為了方便說明整個搜尋的過程。而這兩條路徑本身只能算是兩個不為外界所知的子過程的返回結果。
顯然,從上面的例子可以看出,搜尋增廣路徑的方法就是DFS,可以寫成一個遞歸函數。當然,用BFS也完全可以實現。

至此,理論基礎部份講完了。但是要完成匈牙利算法,還需要一個重要的定理:

如果從一個點A出發,沒有找到增廣路徑,那么無論再從別的點出發找到多少增廣路徑來改變現在的匹配,從A出發都永遠找不到增廣路徑。

要用文字來證明這個定理很繁,話很難說,要么我還得多畫一張圖,我在此就省了。其實你自己畫幾個圖,試圖舉兩個反例,這個定理不難想通的。(給個提示。如果你試圖舉個反例來說明在找到了別的增廣路徑并改變了現有的匹配后,從A出發就能找到增廣路徑。那么,在這種情況下,肯定在找到別的增廣路徑之前,就能從A出發找到增廣路徑。這就與假設矛盾了。)
有了這個定理,匈牙利算法就成形了。如下:

初始時最大匹配為空
for 二分圖左半邊的每個點i
??? do 從點i出發尋找增廣路徑。如果找到,則把它取反(即增加了總了匹配數)。
如果二分圖的左半邊一共有n個點,那么最多找n條增廣路徑。如果圖中共有m條邊,那么每找一條增廣路徑(DFS或BFS)時最多把所有邊遍歷一遍,所花時間也就是m。所以總的時間大概就是O(n * m)。


[cpp]?view plaincopy
  1. #define?N?202??
  2. int?useif[N];???//記錄y中節點是否使用?0表示沒有訪問過,1為訪問過??
  3. int?link[N];???//記錄當前與y節點相連的x的節點??
  4. int?mat[N][N];?//記錄連接x和y的邊,如果i和j之間有邊則為1,否則為0??
  5. int?gn,gm;????//二分圖中x和y中點的數目??
  6. int?can(int?t)??
  7. {??
  8. ????int?i;??
  9. ????for(i=1;i<=gm;i++)??
  10. ????{??
  11. ???????if(useif[i]==0?&&?mat[t][i])??
  12. ???????{??
  13. ???????????useif[i]=1;??
  14. ???????????if(link[i]==-1?||?can(link[i]))??
  15. ???????????{??
  16. ??????????????link[i]=t;??
  17. ??????????????return?1;??
  18. ???????????}??
  19. ???????}??
  20. ????}??
  21. ????return?0;??
  22. }??
  23. int?MaxMatch()??
  24. {??
  25. ????int?i,num;??
  26. ????num=0;??
  27. ????memset(link,0xff,sizeof(link));??
  28. ????for(i=1;i<=gn;i++)??
  29. ????{??
  30. ??????memset(useif,0,sizeof(useif));??
  31. ???????if(can(i))?num++;??
  32. ????}??
  33. ????return?num;??
  34. }??


真正求二分圖的最大匹配的題目很少,往往做一些簡單的變化

變種1:二分圖的最小頂點覆蓋
在二分圖中求最少的點,讓每條邊都至少和其中的一個點關聯,這就是“二分圖的最小頂點覆蓋”。
hdoj1150
二分圖的最小頂點覆蓋數 = 二分圖的最大匹配數


變種2:DAG圖(無回路有向圖)的最小路徑覆蓋
用盡量少的不相交簡單路徑覆蓋有向無環圖(DAG)的所有頂點,這就是DAG圖的最小路徑覆蓋問題。
hdoj1151
DAG圖的最小路徑覆蓋數 = 節點數(n)- 最大匹配數(m)
關鍵:求二分圖的最大匹配數


變種3:?二分圖的最大獨立集
hdoj1068
二分圖的最大獨立集數 = 節點數(n)- 最大匹配數(m)
關鍵:求二分圖的最大匹配數



參考資料:

1,http://imlazy.ycool.com/post.1603708.html

2,杭電ACM PPT

總結

以上是生活随笔為你收集整理的二分匹配详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。