備個份,後面用到再加題目
M67大神的幾句話講解:http://www.matrix67.com/blog/archives/39
二分圖最大匹配問題匈牙利算法
研究了幾個小時,終於明白了。說穿了,就是你從二分圖中找出一條路徑來,讓路徑的起點和終點都是還沒有匹配過的點,並且路徑經過的連線是一條沒被匹配、一條已經匹配過,再下一條又沒匹配這樣交替地出現。找到這樣的路徑後,顯然路徑裏沒被匹配的連線比已經匹配了的連線多一條,於是修改匹配圖,把路徑裏所有匹配過的連線去掉匹配關係,把沒有匹配的連線變成匹配的,這樣匹配數就比原來多1個。不斷執行上述操作,直到找不到這樣的路徑爲止。
bool 尋找從k出發的對應項出的可增廣路
{
while (從鄰接表中列舉k能關聯到頂點j)
{
if (j不在增廣路上)
{
把j加入增廣路;
if (j是未蓋點 或者 從j的對應項出發有可增廣路)
{
修改j的對應項爲k;
則從k的對應項出有可增廣路,返回true;
}
}
}
則從k的對應項出沒有可增廣路,返回false;
}
void 匈牙利hungary()
{
for i->1 to n
{
if (則從i的對應項出有可增廣路)
匹配數++;
}
輸出 匹配數;
}
模板代碼:bool find (int x)
{
for (int i=0;i<G[x].size ();i++){
Edge& e=theEdge[G[x][i]];
if (!vis[e.to]){
vis[e.to]=1;
if (match[e.to]==0 || find (match[e.to])){
match[e.to]=x;
return true;
}
}
}
return false;
}
int hungary ()
{
int cnt=0;
memset (match,0,sizeof (match));
for (int i=0;i<n;i++){
memset (vis,0,sizeof (vis));
if (find (g2l[i]))
cnt++;
}
return cnt;
}