hdu 2255(二分图的最佳完美匹配+KM算法)

hdu 2255

思路:

KM模板题。

二分图的最大完美匹配:有一个二分图,每条边有一个权值,求出权值最大的完美匹配。

KM模板与详解

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 550;
const int INF = 99999999;
int love[maxn][maxn],n;
int vis_g[maxn],vis_b[maxn]; //分别对男,女的标记 
int ex_b[maxn],ex_g[maxn]; //对男女的期望值 
int sk[maxn],link[maxn]; //sk表示男生得到女生的芳心所需的最小期望值,link表示每个男生所配对的女生 
int MIN(int x,int y){
	return x<y?x:y;
}
int MAX(int x,int y){
	return x>y?x:y;
}
bool dfs(int u){ //寻找女生所期望的对象 
	int i,j;
	vis_g[u] = 1;
	for(i=0;i<n;i++){
		if(vis_b[i]) continue;
		int gap = ex_g[u]+ex_b[i]-love[u][i];
		if(gap==0){ //符合要求 
			vis_b[i] = 1;
			if(link[i]==-1||dfs(link[i])){
				link[i] = u;
				return true;
			}
		}
		else sk[i] = MIN(sk[i],gap); //更新男生要得到女生芳心所需的最小值 
	}
	return false;
}
int KM(){
	int i,j;
	fill(link,link+maxn,-1); //每个男生都没有配对 
	memset(ex_b,0,sizeof(ex_b)); //每个男生初始的期望值为0 
	for(i=0;i<n;i++){
		for(ex_g[i]=love[i][0],j=1;j<n;j++) ex_g[i] = MAX(ex_g[i],love[i][j]); //女生初始的期望值是所有与她相连的男生中最帅的 
	}
	for(i=0;i<n;i++){
		fill(sk,sk+maxn,INF); //一开始女生对男生地期望值为INF,假设所有男生都得不到女生的青睐 
		while(1){
			memset(vis_b,0,sizeof(vis_b));
			memset(vis_g,0,sizeof(vis_g));
			if(dfs(i)) break; //如果女生找到合适的男生 
			int d = INF;
			for(j=0;j<n;j++)
			if(!vis_b[j]) d = MIN(d,sk[j]); //这个女生要找到合适男生所需要降低的最小标准 
			for(j=0;j<n;j++){
				if(vis_g[j]) ex_g[j] -= d; //女生的期望值下降d,以便于找到合适的男生。 
				if(vis_b[j]) ex_b[j] += d; //这个男生得到多个女生的青睐,男生地期望值上升 
				else sk[j] -= d; //男生所需要得到女生芳心的最小期望降低d 
			}
		}
	}
	int ans = 0;
	for(i=0;i<n;i++) ans += love[link[i]][i];//求出第i个男生和他的女票的期望值。 
	return ans;
}
int main(void)
{
	int i,j;
	while(~scanf("%d",&n)){
		for(i=0;i<n;i++)
			for(j=0;j<n;j++) scanf("%d",&love[i][j]); //输入每个女生对每个男生的期望值 
		printf("%d\n",KM());
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/89237369
今日推荐