標籤:for algo 概念 size cstring ++ mem https 學習
首先二分圖匹配的基礎概念得清楚:
二分圖: 設G=(V,E)是一個無向圖,如果頂點V可分割為兩個互不相交的子集(A,B),並且圖中的每條邊(i,j)所關聯的兩個頂點i和j分別屬於這兩個不同的頂點集(i in A,j in B),則稱圖G為一個二分圖。
匹配: 兩兩不含公用端點的邊集合M稱為匹配(簡單的說就是右邊的點只能連一條邊)
極大匹配: 指在當前已完成的匹配下,無法再通過增加未完成匹配的邊的方式來增加匹配的邊數
最大匹配: 所有極大匹配當中邊數最大的一個匹配
增廣路: 若P是圖G中一條連通兩個未匹配頂點的路徑,並且屬於M的邊和不屬於M的邊(即已匹配和待匹配的邊)在P上交替出現,則稱P為相對於M的一條增廣路徑.(百度百科)
簡單理解就是 假如左邊集合A點與右邊集合P點 有一條已經匹配的邊,而左邊集合B點也與右邊集合P點 有一條未匹配的邊,能不能讓A點去匹配右邊集合的其他點。從而讓B點俘獲P點,達到匹配數量增大的情況。 個人理解。。如有錯誤,歡迎指正。
演算法步驟:
1.將集合清空為0.
2.選擇一個新的節點尋找增廣路
3.重複2操作直到找不出增廣路徑為止
這裡的Flash示範非常不錯,簡單易懂 https://comzyh.com/blog/archives/148/。
例題:
Usaco-4.2.2 The Perfect Stall
二分圖匹配模板題目
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 bool used[1005],cow[233][233]; 6 int fa[1005],tot; 7 int n,m; 8 9 bool find(int x){10 for(int i=1;i<=m;i++){11 if(!used[i] && cow[x][i]){12 used[i]=true;13 if(!fa[i] || find(fa[i])){14 fa[i]=x;15 return 1;16 }17 }18 }19 return 0;20 }21 22 int main(){23 scanf("%d%d",&n,&m);24 for(int i=1;i<=n;i++){25 int x;26 scanf("%d",&x);27 for(int j=1;j<=x;j++){28 int a;29 scanf("%d",&a);30 cow[i][a]=1;31 }32 }33 for(int i=1;i<=n;i++){34 memset(used,0,sizeof(used));35 if(find(i)) tot++;36 }37 printf("%d\n",tot);38 }
二分圖匹配-匈牙利演算法【學習】