匈牙利演算法-二分圖的最大匹配
阿新 • • 發佈:2020-08-03
匈牙利(Hungarian)演算法-二分圖的最大匹配問題
上述視訊涉及到的一個打卡題目杭電OJ-2063-過山車
我的程式碼如下:(下面的程式碼同視訊裡的稍有不同,或者說是男女正好相反吧)
#include<bits/stdc++.h> using namespace std; const int maxn = 505; int dict[maxn][maxn]; int vis[maxn]; int nxt[maxn];//某個男生有沒有女生 int k,m,n;//m女生,n男生 bool match(int x) { for(int i=1;i<=n;i++)//遍歷每個男生 { if(dict[x][i] && !vis[i])//如果x女生對男生有意向且該男生還沒有被訪問過 { vis[i]=1;//該男生在該女生的匹配階段已經被訪問過 if(nxt[i]==0 || match(nxt[i]))//如果男生沒有被配對或者該男生配對的女生可以變換 { nxt[i]=x; return true; } } } return false; } int solve() { int sum = 0; for(int i = 1;i<=m;i++)//遍歷每個女生 { memset(vis,0,sizeof(vis)); if(match(i))sum++; } return sum; } int main() { while(cin>>k && k) { //讀入資料 memset(dict,0,sizeof(dict)); cin>>m>>n; for(int i=0;i<k;i++) { int g,b; cin>>g>>b; dict[g][b]=1; } //初始化 memset(nxt,0,sizeof(nxt)); //解決問題 cout<<solve()<<endl; } return 0; }
其實,上面那個視訊並沒有過多的涉及到匈牙利演算法的內容,
也沒有很好的講明白遞迴演算法的實現。
不過,這至少讓你對匈牙利演算法的大致思想有所瞭解。
下面,將會詳細說明匈牙利演算法及其前置概念。
接下來是一個CSDN的博文。
這個部落格完全沒有程式碼,但是它十分清晰的講解了匈牙利演算法演算法精髓。
注意演算法關鍵詞:二部圖(二分圖)、增廣路、遞迴、後來者居上
結合上面的解釋以及打卡題目的程式碼,我們可以基本得到一個模板:
const int MAXN = 500; int M, N; //M, N分別表示左、右側集合的元素數量 int Map[MAXM][MAXN]; //鄰接矩陣存圖 int p[MAXN]; //記錄當前右側元素所對應的左側元素 bool vis[MAXN]; //記錄右側元素是否已被訪問過 bool match(int i) { for (int j = 1; j <= N; ++j) if (Map[i][j] && !vis[j]) //有邊且未訪問 { vis[j] = true; //記錄狀態為訪問過 if (p[j] == 0 || match(p[j])) //如果暫無匹配,或者原來匹配的左側元素可以找到新的匹配 { p[j] = i; //當前左側元素成為當前右側元素的新匹配 return true; //返回匹配成功 } } return false; //迴圈結束,仍未找到匹配,返回匹配失敗 } int Hungarian() { int cnt = 0; for (int i = 1; i <= M; ++i) { memset(vis, 0, sizeof(vis)); //重置vis陣列 if (match(i)) cnt++; } return cnt; }
OK