1. 程式人生 > >匈牙利演算法(二分圖匹配問題)

匈牙利演算法(二分圖匹配問題)

匈牙利演算法(二分圖匹配問題)

問題連結(杭電2063題):http://acm.hdu.edu.cn/showproblem.php?pid=2063
參考部落格:https://blog.csdn.net/cillyb/article/details/55511666
找伴侶是個遞迴的過程,最最關鍵的字就是“騰”字
其原則大概是:有機會上,沒機會創造機會也要上

#include<iostream>
#include<cstring>
using namespace std;
/*匈牙利演算法,二分圖匹配,杭電2063題*/
int k,m,n;  //k為組合數,m為左側數,n為右側點數
bool vis[520];   //這個右側點是否被找過 
int line[520][520];  
//line表示左側女生和右側男生是否相互喜歡
int peidui[520];
//peidui表示右側男生匹配到的左側女生的點 
bool find(int x)  //匈牙利演算法是遞迴的 
{
	for(int i=1;i<=n;i++)  //遍歷圖的左側所有男生 
	{
		if(line[x][i]==1&&!vis[i])  //如果該右側男生沒有被訪問過,並且左側x喜歡右側i 
		{
			vis[i]=true;  //設定該右側男生被訪問過 
			if(peidui[i]==0||find(peidui[i]))  //如果右側男生沒有被配對,或者右側的原配可以尋找到新的配對 
			{
				peidui[i]=x;  //則該右側點匹配到該左側點 
				return true;  //返回結果真 
			}
		}
	} 
	return false;  //否則返回結果假 
}
int main()
{
	int ans;  //最大配對數 
	int g,b;  //g為圖的左側,b為右側 
	while(cin>>k&&k)  //輸入組合數 
	{
		cin>>m>>n;  //輸入圖左側點的個數、圖右側點的個數 
		memset(line,0,sizeof(line));  //初始化鄰接矩陣 
		memset(peidui,0,sizeof(peidui));  //初始化訪問陣列 
		for(int i=0;i<k;i++)
		{
			cin>>g>>b;  //輸入左側點、右側點 
                        line[g][b]=1;	//g左側喜歡b右側,設定為有邊 
		}
		ans=0;
		for(int i=1;i<=m;i++)  //遍歷所有左側點 
		{
			memset(vis,false,sizeof(vis));  //每次都需要初始化訪問陣列 
			if(find(i))    ans++;  //如果配對成功,結果自增 
		}
		cout<<ans<<endl; //輸出結果 
	}
}