HDU2255 【模板】KM算法

题目地址


KM算法

易错点:

  • 配不上的话可能连机会都没有了,所以不要太天真(vb[y]=1(占有)要在配得上(gap==0,门当户对)的前提下).
  • 没缘分的话最好就不要妄想(if(vb[y])continue;).

费用流算法

(qwq)


#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=310,INF=1<<30;
int la[N],lb[N],w[N][N],match[N],delta,n;
bool va[N],vb[N];
bool dfs(int x){
	va[x]=1;
	for(int y=1;y<=n;y++){
		if(vb[y])continue;
		int gap=la[x]+lb[y]-w[x][y];
		if(gap==0){
			vb[y]=1;
			if(!match[y]||dfs(match[y])){
				match[y]=x;
				return 1;
			}
		}else delta=min(delta,gap);
	}
	return 0;
}
int KM(){
	for(int x=1;x<=n;x++){
		la[x]=-INF;
		for(int y=1;y<=n;y++)
			la[x]=max(la[x],w[x][y]);
	}
	for(int x=1;x<=n;x++){
		while(1){
			memset(va,0,sizeof(va));
			memset(vb,0,sizeof(vb));
			delta=INF;
			if(dfs(x))break;
			for(int i=1;i<=n;i++){
				if(va[i])la[i]-=delta;
				if(vb[i])lb[i]+=delta;
			}
		}
	}
	int ans=0;
	for(int y=1;y<=n;y++)
		ans+=w[match[y]][y];
	return ans;
}
void init(){
	memset(lb,0,sizeof(lb));
	memset(match,0,sizeof(match));
}
int main(){
	while(scanf("%d",&n)!=EOF){
		init();
		for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&w[i][j]);
		printf("%d\n",KM());
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值