匈牙利演算法--二分圖的最大匹配

Annaprincess發表於2024-08-03

匈牙利演算法--二分圖的最大匹配

給定一個二分圖,其中左半部包含 n1個點(編號 1n1),右半部包含 n2 個點(編號 1n2),二分圖共包含 m 條邊。

資料保證任意一條邊的兩個端點都不可能在同一部分中。

請你求出二分圖的最大匹配數。

二分圖的匹配:給定一個二分圖 G,在 G的一個子圖 M 中,M的邊集 {E}中的任意兩條邊都不依附於同一個頂點,則稱 M 是一個匹配。

二分圖的最大匹配:所有匹配中包含邊數最多的一組匹配被稱為二分圖的最大匹配,其邊數即為最大匹配數。

輸入格式

第一行包含三個整數 n1n2m

接下來 m 行,每行包含兩個整數 uv,表示左半部點集中的點 u 和右半部點集中的點 v之間存在一條邊。

輸出格式

輸出一個整數,表示二分圖的最大匹配數。

資料範圍

1n1,n2500
1un1
1vn2
1m105

輸入樣例:

2 2 4
1 1
1 2
2 1
2 2

輸出樣例:

2

匈牙利演算法--二分圖的最大匹配

最大匹配問題分析:

從左到右每個男生搭配不同的女生

做法是利用鄰接表存放從左到右的圖

然後遍歷所有男生看每個男生選不同的女生最多有幾個男生能實現-->對於每個男生遍歷他相連線的女生,前提是女生沒被遍歷,且女生沒有被別的男生選或者選這個女生的男生不選這個女生還有備選女生。find函式

match陣列:match[i]=a表示第i個女生搭配第a個男生

男女用數字1~表示

#include<bits/stdc++.h>
//單向,從左到右
using namespace std;
int n1,n2,m;
const int N=600;//一邊的點數
const int M=100008;//邊數,因為單向從左到右所以不需要乘2
bool st[N];//這個頂點有沒有訪問過,右邊的頂點
//鄰接表
int h[N];//頭指標
int e[M];//當前
int ne[M];//下一個
int match[N];//女搭配哪個男,N存女生數
int idx;
void add(int a,int b){//鄰接表
e[idx]=b;
ne[idx]=h[a];
h[a]=idx;
idx++;
}
bool find(int a){
for(int i=h[a];i!=-1;i=ne[i]){
int t=e[i];
if(!st[t]){//這個相鄰點沒遍歷過
st[t]=true;//遍歷
if(match[t]==0||find(match[t])){
match[t]=a;
return true;
}
}
}
return false;
}
int main(){
cin>>n1>>n2>>m;
memset(h,-1,sizeof h);
int a,b;
while(m--){//鄰接表
cin>>a>>b;
add(a,b);
}
int res=0;
for(int i=1;i<=n1;i++){
memset(st,false,sizeof st);
if(find(i)){
res++;
}
}
cout<<res;
return 0;
}

相關文章