擴充路徑演算法是一個找二分圖匹配的算法,可以無向的 - 二分圖進行 與 的匹配,同時也可以用演算法的方式,將 Kőnig 定理證出來
有些人會將此演算法與匈牙利演算法搞混,所以特別需要說明一下,匈牙利演算法是使用矩陣尋找二分圖最大權完美匹配,而擴充路徑演算法則是使用單純的連邊關係,反覆迭代跑 DFS 或 BFS 來完成二分圖最大基數匹配。兩者的時間複雜度也有差異,匈牙利演算法的時間為 ,而擴充路徑演算法則是
似乎也有人將擴充路徑演算法稱作 Kuhn's algorithm
如果想完全理解本篇內容,可以閱讀前面的章節匹配與霍爾定理、Kőnig 定理
擴充路徑演算法顧名思義需要使用擴充路徑 (又稱為增廣路徑) 的性質,也就是透過其定義中的「兩終點都是未匹配點」來尋找新的匹配
一張 -二分圖 、一個在 中的匹配 ,在 中的未飽和點集
令 與 為已經碰到的節點集。我們可以從 探索一條 -alternating path,並把 中有探索過的節點打上記號。當碰到一個節點時,紀錄此節點是被誰碰到的
初始化: 、
迭代: 從 探索一條 -alternating path
這是我們原本的 -二分圖。其中綠色邊為匹配 中的邊、 初始為 ,即 中的未配對點集,且 中的節點皆未標記
我們可以挑 中最左邊的未標記節點來探索,發現他的鄰居是一個飽和的點,所以我們可以將鄰居加入 ,其匹配點加入
接下來我們可以再挑一個 中未標記的節點,將其鄰居探訪之後發現可以產生一條新的擴充路徑,因兩終點皆未匹配。我們將其視為新的匹配並停止迭代
從上面的例子可以發現,我們可以反覆尋找一條新的擴充路徑,直到 時,也就是匹配數等於最小點覆蓋數的時候,就可以找到最大匹配
以下例子,我們延續上面的 -二分圖。其中綠色邊為匹配 中的邊、 初始為 ,即 中的未配對點集,且 中的節點皆未標記
我們可以挑 中最左邊的未標記節點來探索,發現他的鄰居是一個飽和的點,所以我們可以將鄰居加入 ,其匹配點加入
接下來我們可以再挑一個 中最右邊未標記的節點,並拜訪其還沒在 中的鄰居,再沿著匹配邊,又發現新的未標記點,將鄰居與其匹配點分別加入 與 。因為鄰居探訪完了,所以打上標記
接下來我們可以挑右邊數來第一與第三個 中的節點,發現他們的鄰居都已經在 裡面了,所以我們沒什麼好做的,就把他們打上標記
最後只剩從左數來第二個節點上未打上標記,因此我們先去探訪他的鄰居。由於發現他的其中一個鄰居是未飽和的,我們可以找到一條擴充路徑,並結束迭代。根據 Berge 定理,此擴充路徑中,我們可以找到更大的匹配
↓
↓
↓
最後,由於 中仍有一節點尚未飽和,我們再迭代一次,但是因為篇幅的緣故,跳個步驟,詳細過程可以自己畫畫看。最終,圖會長這樣
可以發現,,且 是最小點覆蓋
對二分圖重複執行擴充路徑演算法,最終會產生相同大小的匹配與點覆蓋
由於擴充路徑演算法本來就會產生擴充路徑,我們只需要證明他會產生一組大小為 的點覆蓋 即可
一條從 進入 的 -alternating path 只會在 中的邊上,因此所有 的節點 只會通過 來配對 ,且並沒有任何一條 中的節點會從 到 。此外,也不會有任何 外的邊是這種情況。當一條路徑到達 時,可以繼續沿著不是 的邊走,並把鄰居都加入 中。因演算法在停止之前會標記所有 的節點,所有從 出發的點都會到達
此演算法只會把飽和的節點放進 ,也就是每個 都會通過 配對到 中的節點。由於 且每個 中的節點都是飽和的, 中與 關聯的邊沒有辦法碰到 ,所以他們與使 飽和的邊是不同的邊。藉由前面的推理,在演算法中我們可以發現 有最少 條邊。因沒有辦法產生大於此匹配的點覆蓋,因此我們得到
每次迭代都要找一個所有的點
而匹配數量有可能會等於邊數
因此總時間複雜度 :
此方法簡而言之就是用 DFS 或 BFS 做出反覆尋找擴充路徑的過程。其實這不難理解,因為原本的算法我們需要一直停下迭代步驟,然後再重新來過,這會造成大量的時間損失
詳細步驟文字敘述會看起來很燥,看程式碼會比較好懂,在此就不多加贅述
這邊使用鄰接矩陣實作,空間複雜度非常差,如果想省空間的話建議還是使用鄰接串列
總時間複雜度 :
來源: Zerojudge i179. 防守城堡 (Defense)
題目是說在一個 方格棋盤上,可以在下方與右方的邊界放置砲台,也可以在每格放置十字形的陷阱,十字形的陷阱會摧毀整個橫縱座標的所有砲台。小東會放置 個十字陷阱,且希望一個陷阱最堆摧毀一個砲台就好,問最多可以放幾台砲台
是座標
可以視每個十字陷阱都會匹配下與右兩個位置
如下圖,將能放置砲台的位置編號,並把陷阱當成邊。我們就可以輕易發現,此問題可以轉化成兩砲台匹配的問題
匹配完之後再加上未匹配的砲台就會是答案
CSES School Dance (裸題)
Zerojudge h901. 電橘子與電耗子 (二分搜 + 配對)
Zerojudge c484. kevin 的西洋棋 (奇偶建圖)
Zerojudge d739. 最少路径覆盖 (把每個點拆成出點/入點,再考慮連邊與匹配要怎麼轉換)
Zerojudge c455. 4. 警力配置 (Kőnig 定理裸題,不知道為什麼 可以過,可能沒跑滿吧)
SWERC2023 Problem B. Supporting everyone (簡單的)
2020 TOPC Problem G.Garden
OnlineJudge 259 - Software Allocation (想辦法轉成二分圖匹配吧加油)
OnlineJudge 10080 - Gopher II (跑的到就建邊,記得多比測資)
SWERC2014 Problem D.Book Club (檢查是否有完美匹配)
Codeforces Gym 101201 G.Maximum Islands (連通塊 + 二分圖最大獨立集)
Codeforces Round 668 (Div. 1) Problem E. Bricks (建圖很有趣的有趣的怪題)
CodeForces - 793G Oleg and chess (閱讀題,建圖很有趣,可以用線段樹或是 bitset 優化,推薦 bitset 程式碼會短很多)
ICPC Thailand National Competition 2024 Problem C. Cattering (這題好像只能 flow 或 Hopcroft-Karp)
Codeforces gym 102433 I. Error Correction (閱讀題,建圖很有趣)
ECPC2016 Problem C. The Wall (坐標系 有趣)
ShanC 程式競賽筆記
作者: ShanC
更新: 2025/1/31