KM算法

学了下km算法....
写了道题
然后一遍过了2333

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; 
#define INF 0x3f3f3f3f
const int maxn = 1007; 
int kind[maxn][maxn]; 
int match[maxn],ex_gril[maxn],ex_boy[maxn],vis_b[maxn],vis_g[maxn];  
int n,slack[maxn]; 
bool dfs(int g) {
	vis_g[g] = 1;
	for(int i = 1;i <= n;++ i) {
		if(vis_b[i]) continue; 
		int res = ex_gril[g] + ex_boy[i] - kind[g][i]; 
		if(!res) {
			vis_b[i] = true; 
			if(match[i]  == -1|| dfs(match[i])) {
				match[i] = g; return true; 
			}
		} else slack[i] = std::min(slack[i],res); 
	}
	return false;
}	
int km() { 
	memset(match,-1,sizeof match) ; 
	memset(ex_boy,0,sizeof ex_boy); 
	for(int i = 1;i <= n;++ i) {
		ex_gril[i] = kind[i][1]; 
		for(int j = 1;j <= n;++ j) 
			ex_gril[i] = std::max(ex_gril[i],kind[i][j]); 
	}
	for(int i = 1;i <= n;++ i) {
		fill(slack + 1,slack + n + 1,INF); 
		while(11101001) {
			memset(vis_g,0,sizeof vis_g);
			memset(vis_b,0,sizeof vis_b);
			if(dfs(i)) break; 
			int d = INF;
			for(int j = 1;j <= n;++ j) if(!vis_b[j]) d = std::min(d,slack[j]);
	       		for(int j = 1;j <= n;++ j) {
	       			if(vis_g[j]) ex_gril[j] -= d;
 				if(vis_b[j]) ex_boy[j] += d;
				else slack[j] -= d;
			}			
		
		}
	}
	int ret = 0;
	for(int i = 1;i <= n;++ i) ret += kind[match[i]][i]; 
	return ret;
} 
int main() {  
	while(scanf("%d",&n) == 1) {
		for(int i = 1;i <= n;++ i) 
			for(int j = 1;j <= n;++ j) 
				scanf("%d",&kind[i][j]); 
		printf("%d\n",km()); 
	}
        return 0;
}

posted @ 2018-05-05 21:40  zzzzx  阅读(195)  评论(0编辑  收藏  举报