二分圖最大匹配
為了描述方便將兩個集合分成左和右兩個部分,所有匹配邊都是橫跨左右兩個集合,可以假想成男女配對。
假設圖有 \(n\) 個頂點,\(m\) 條邊。
題目描述
給定一個二分圖 \(G\),即分左右兩部分,各部分之間的點沒有邊連接,要求選出一些邊,使得這些邊沒有公共頂點,且邊的數量最大。
增廣路算法 Augmenting Path Algorithm
因為增廣路長度為奇數,路徑起始點非左即右,所以我們先考慮從左邊的未匹配點找增廣路。 注意到因為交錯路的關係,增廣路上的第奇數條邊都是非匹配邊,第偶數條邊都是匹配邊,於是左到右都是非匹配邊,右到左都是匹配邊。 於是我們給二分圖 定向,問題轉換成,有向圖中從給定起點找一條簡單路徑走到某個未匹配點,此問題等價給定起始點 \(s\) 能否走到終點 \(t\)。 那麼只要從起始點開始 DFS 遍歷直到找到某個未匹配點,\(O(m)\)。 未找到增廣路時,我們拓展的路也稱為 交錯樹。
性質
因為要枚舉 \(n\) 個點,總複雜度為 \(O(nm)\)。
實現
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | |
轉為網絡最大流模型
二分圖最大匹配可以轉換成網絡流模型。
將源點連上左邊所有點,右邊所有點連上匯點,容量皆為 \(1\)。原來的每條邊從左往右連邊,容量也皆為 \(1\),最大流即最大匹配。
如果使用 Dinic 算法 求該網絡的最大流,可在 \(O(\sqrt{n}m)\) 求出。
Dinic 算法分成兩部分,第一部分用 \(O(m)\) 時間 BFS 建立網絡流,第二步是 \(O(nm)\) 時間 DFS 進行增廣。
但因為容量為 \(1\),所以實際時間複雜度為 \(O(m)\)。
接下來前 \(O(\sqrt{n})\) 輪,複雜度為 \(O(\sqrt{n}m)\)。\(O(\sqrt{n})\) 輪以後,每條增廣路徑長度至少 \(\sqrt{n}\),而這樣的路徑不超過 \(\sqrt{n}\),所以此時最多隻需要跑 \(\sqrt{n}\) 輪,整體複雜度為 \(O(\sqrt{n}m)\)。
代碼可以參考 Dinic 算法 的參考實現,這裏不再給出。
補充
二分圖最小點覆蓋(König 定理)
最小點覆蓋:選最少的點,滿足每條邊至少有一個端點被選。
二分圖中,最小點覆蓋 \(=\) 最大匹配。
證明
將二分圖點集分成左右兩個集合,使得所有邊的兩個端點都不在一個集合。
考慮如下構造:從左側未匹配的節點出發,按照匈牙利算法中增廣路的方式走,即先走一條未匹配邊,再走一條匹配邊。由於已經求出了最大匹配,所以這樣的「增廣路」一定以匹配邊結束,即增廣路是不完整的。在所有經過這樣「增廣路」的節點上打標記。則最後構造的集合是:所有左側未打標記的節點和所有右側打了標記的節點。
首先,這個集合的大小等於最大匹配。左邊未打標記的點都一定對應着一個匹配邊(否則會以這個點為起點開始標記),右邊打了標記的節點一定在一條不完整的增廣路上,也會對應一個匹配邊。假設存在一條匹配邊左側標記了,右側沒標記,左邊的點只能是通過另一條匹配邊走過來,此時左邊的點有兩條匹配邊,不符合最大匹配的規定;假設存在一條匹配邊左側沒標記,右側標記了,那就會從右邊的點沿着這條匹配邊走過來,從而左側也有標記。因此,每一條匹配的邊兩側一定都有標記(在不完整的增廣路上)或都沒有標記,匹配邊的兩個節點中必然有一個被選中。
其次,這個集合是一個點覆蓋。由於我們的構造方式是:所有左側未打標記的節點和所有右側打了標記的節點。假設存在左側打標記且右側沒打標記的邊,對於匹配邊,上一段已經説明其不存在,對於非匹配邊,右端點一定會由這條非匹配邊經過,從而被打上標記。因此,這樣的構造能夠覆蓋所有邊。
同時,不存在更小的點覆蓋。為了覆蓋最大匹配的所有邊,至少要有最大匹配邊數的點數。
二分圖最大獨立集
最大獨立集:選最多的點,滿足兩兩之間沒有邊相連。
因為在最小點覆蓋中,任意一條邊都被至少選了一個頂點,所以對於其點集的補集,任意一條邊都被至多選了一個頂點,所以不存在邊連接兩個點集中的點,且該點集最大。因此二分圖中,最大獨立集 \(=n-\) 最小點覆蓋。
習題
UOJ #78. 二分圖最大匹配
模板題
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
參考資料
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:accelsao, thallium, Chrogeek, Enter-tainer, ksyx, StudyingFather, H-J-Granger, Henry-ZHR, countercurrent-time, william-song-shy, 5ab-juruo, XiaoQuQuSD
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用