很早之前就學過最近再溫習一下,畢竟匈牙利演算法雖然在解決二分圖最大匹配問題上複雜度不如dinic,但程式設計複雜度低很多,而且不容易寫錯。
其實如果對網路流有所涉獵,再來學習二分圖最大匹配問題就太好理解了。此處預設讀者已經了解了二分圖最大匹配的問題模型及基本的網路流知識,若對網路流沒有了解可以參見我的另一篇部落格網路流的核心思想.
二分圖問題可以很容易轉化成網路流模型,即在原圖中新增一源一匯,源點與左部各點相連,容量為1
11,右部各點與匯點相連,容量為1
11。由是我們只需跑一遍最大流即可求得二分圖最大匹配。例如對於下面這幅圖
mermaid終於畫的像個二分圖了我們只需將其轉化為這樣的網路
即可在網路上跑最大流求解。而我們經常用到的網路流演算法如dinic其實是基於ford-fulkerson的思想即增廣路的思想,我們很容易聯想,在二分圖這樣的特殊圖上,是否有更簡易的找增廣路的辦法呢?顯然是有的,而且特別暴力。我們重新考慮乙個的二分圖。我們依次考慮左部的點,然後遍歷它的鄰點,然後尋找乙個可匹配點,然後
這裡mermaid把1畫到下面了,但我們還是以編號順序而不是視覺順序來考慮首先考慮左部的1
11,我們考慮它的鄰點,發現4
44未匹配,直接產生匹配。
乙個點有且只能產生一對匹配,故當匹配生成後,我們直接考慮左部下乙個點222。
2
22只與右部的4
44有邊相連,但此時4
44已產生匹配,2
22並不能與4
44產生匹配,怎麼處理這種情況?如果選擇跳過2
22,那麼對於後面的3
33也是一樣跳過的情況,最終產生的匹配只有1
11對,顯然有問題。聯想一下之前介紹的網路流模型解決的方法,其實這裡我們就是要找增廣。
尋找增廣路其實有乙個很簡單暴力的方法,就是看當前已匹配的右部的點對應的左部的點的鄰點是否還有能匹配的點,如果有那麼就讓這個左部的點跟新的點匹配,為當前點騰出空間(顯然這是乙個遞迴的過程)。
我們具體情況分析一下,現在考慮左部的點2
22,其唯一相連的右部的點4
44已與左部的1
11匹配。按照上面的說法,我們僅需為1
11找乙個新的匹配點。我們遍歷1
11的所有鄰點,4
44被訪問了,所以我們找到右部的5
55,發現5
55尚未匹配,我們可以讓1
11匹配5
55,再讓2
22匹配之前的4
44,以達到增廣目的。
可以自行在更複雜的圖上手動嘗試這一操作加深理解。顯然,每對乙個左部的點做上述操作,至多只會增加1
11對匹配。而這一做法其實是基於一種貪心的思想,即每次操作答案都只會增不會減。
//
// created by visors on 2020/10/7.
//// 題目名:p3386 【模板】二分圖最大匹配
// 演算法:匈牙利演算法
// 用途:二分圖最大匹配
// 時間複雜度:o(nm)
//#include
using
namespace std;
int n, m, vertexnum, edgenum;
struct edge };
vector edges;
// 邊集
vector<
int> heads;
// 首邊集
vector<
bool
> vis;
// 點訪問標記
vector<
int> match;
// 點匹配記錄
inline
void
addedge
(int u,
int v)
bool
dfs(
int u)}}
return
false;}
inline
inthungary()
return max_match;
}int
main()
cout <<
hungary()
<< endl;
return0;
}
匈牙利演算法
匈牙利演算法 edmonds演算法 步聚 1 首先用 標記x中所有的非m頂點,然後交替進行步驟 2 3 2 選取乙個剛標記 用 或在步驟 3 中用 yi 標記 過的x中頂點,例如頂點xi,如果xi與y為同一非匹配邊的兩端點,且在本步驟中y尚未被標記過,則用 xi 去標記y中頂點y。重複步驟 2 直至...
匈牙利演算法
匈牙利演算法用來解決二分圖的最大匹配問題。乙個典型的最大匹配問題的描述如下 乙個公司有n項工作,m個員工。每個員工能勝任n項工作中的幾項 0 n 工作。問題是,如何分配才能使得被處理的工作數最大。當然,如果公司裡人員很多,每項工作都有很多員工可以勝任,那麼使每項工作都有人處理的方案是顯而易見的。但遇...
匈牙利演算法
二分圖匹配的演算法,二分圖就是把圖上的點分成兩個互不相交的點集,而圖中的邊的端點只能分別屬於這兩個點集.二分圖的匹配,就是婚配問題,左邊的點集男性,右邊的點集女性,然後相互配對 一夫一妻 最大匹配就是讓好事最多.匈牙利演算法可以實現這個東西.匈牙利演算法怎麼實現的這個東西.這個比較多.如下 incl...