【菜鸡的DailyTopic】KM算法(带权二分图最大匹配)模板

算法讲解:https://blog.csdn.net/u014097230/article/details/51554905

算法模板:

// KM
#include 
using namespace std;
const int maxLen = 256;
bool visBoy[maxLen],visGirl[maxLen];
int exBoy[maxLen],exGirl[maxLen];
int match[maxLen];
int slack[maxLen],love[maxLen][maxLen];
int b,g;
bool dfs(int g)
{
	visGirl[g] = true;
	for(int i=1;i<=b;i++) {
		if(visBoy[i]) continue;
		int gap = exGirl[g] + exBoy[i] - love[g][i];
		if(gap == 0) {
			visBoy[i] = true;
			if(match[i] == -1 || dfs(match[i])) {
				match[i] = g;
				return true;
			}
		}
		else 
			slack[i] = min(slack[i],gap);
	}
	return false;
}
void KM()
{
	memset(match,-1,sizeof match); //男生的匹配
	memset(exGirl,0,sizeof exGirl);  //女生的期望
	memset(exBoy,0,sizeof exBoy);
	
	for(int i=1;i<=g;i++) {
		for(int j=1;j<=b;j++)
			exGirl[i] = max(exGirl[i],love[i][j]); //计算每个女生的最大期望
	}

	for(int i=1;i<=g;i++) {  //为每个女生寻找满意的男生,男生不挑,有就行
		memset(slack,0x3f3f3f3f,sizeof slack);
		while( true) {
			memset(visGirl,false,sizeof visGirl);
			memset(visBoy,false,sizeof visBoy);

			if(dfs(i)) break;
			
			int cut = 0x3f3f3f3f;
			for(int i=1;i<=b;i++)
				if(!visBoy[i])	cut = min(cut,slack[i]);  // 女生最低要降低多少要求 

			for(int i=1;i<=g;i++) 
				if(visGirl[i])	exGirl[i] -= cut;  //找不到男朋友就降低要求
			for(int i=1;i<=b;i++) {
				if(visBoy[i])	exBoy[i] += cut;  //有人喜欢就飘了 
				slack[i] -= cut;  //女生期望降了,男生有媳妇的要求就笑了
			}
		}
	}

}
int main()
{
	scanf("%d%d",&g,&b); //女生人数 男生人数 
	for(int i=1;i<=g;i++) {
		for(int j=1;j<=b;j++)
			scanf("%d",&love[i][j]);
	}

	KM();
	
	int tot = 0;
	for(int i=1;i<=b;i++)
		tot += love[match[i]][i];
	printf("%d\n",tot);
}

习题:

HDU - 2255 奔小康赚大钱  https://blog.csdn.net/weixin_42765557/article/details/98654974

你可能感兴趣的:(DailyTopic,模板)