码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 2255 & KM模板

时间:2016-02-17 08:16:10      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:

题意:

  一张完备二分图求最优完备匹配。

SOL:

  这题就不讲什么sol了。。。毕竟是裸的KM,不会的话可以看老人家的大白鼠,一些问题看代码注释。讲讲经历(悲惨的经历)

  刚打完,自信地交上去发现MLE...一脸大雾...然后才开始看数据..300^4啊...看起来会炸的样子,那么加个优化好了。还是MLE!真是奇了怪了。然后就在提交里看别人是不是用的邻接表——清一色邻接矩阵!再想想KM搞的都是完备图啊邻接表和邻接矩阵用起来没什么不同。那么没问题啊?然后交来交去交了8次...直到zyh大神——虽然他从不用KM,但是他居然一眼道出真相——没看到递归啊。

  woc!!!HDU!!!显然我是爆栈了!!终于经历了一次爆栈的体验啊。。。也不枉此生了。

CODE:

/*==========================================================================
# Last modified: 2016-02-16 18:17
# Filename: hdu2255.cpp
# Description: 
==========================================================================*/
#define me AcrossTheSky 
#include <cstdio> 
#include <cmath> 
#include <ctime> 
#include <string> 
#include <cstring> 
#include <cstdlib> 
#include <iostream> 
#include <algorithm> 
  
#include <set> 
#include <map> 
#include <stack> 
#include <queue> 
#include <vector> 
#define lowbit(x) (x)&(-x) 
#define INF 0x3f3f3f3f
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++) 
#define FORP(i,a,b) for(int i=(a);i<=(b);i++) 
#define FORM(i,a,b) for(int i=(a);i>=(b);i--) 
#define ls(a,b) (((a)+(b)) << 1) 
#define rs(a,b) (((a)+(b)) >> 1) 
#define maxn 310
using namespace std; 
typedef long long ll; 
typedef unsigned long long ull; 
/*==================split line==================*/ 
int n;
int slack[maxn],w[maxn][maxn],lx[maxn],ly[maxn],link[maxn]; //lx,ly表示节点函数,link表示T集每点对应的S集点
bool S[maxn],T[maxn]; //是否在相等子图中

bool match(int x){
	S[x]=true;
	FORP(i,1,n){
		if (T[i]) continue;
		if (lx[x]+ly[i]==w[x][i]){		
				T[i]=true;
				if (!link[i] || match(link[i])){
					link[i]=x;
					return true;
				}
			}
		else slack[i]=min(slack[i],lx[x]+ly[i]-w[x][i]); //用slack计算出松弛量
	}
	return false;
}
void updata(){
	int a=INF;
	FORP(j,1,n) if (!T[j])
		a=min(a,slack[j]);
	FORP(i,1,n) {
		if (S[i]) lx[i]-=a;
		if (T[i]) ly[i]+=a;
		else slack[i]-=a;
	}
	return;
}
void KM(){
	memset(lx,0,sizeof(lx));
	memset(ly,0,sizeof(ly));
	FORP(i,1,n){
		link[i]=0;
		//S[i]=T[i]=false;
		FORP(j,1,n)
			lx[i]=max(lx[i],w[i][j]);
	}
	FORP(i,1,n){ //这里要循环N次我一直有点雾...
		FORP(j,1,n) slack[j]=INF;
		while(1){
			memset(S,false,sizeof(S));
			memset(T,false,sizeof(T));
			if (match(i)) break;
				else updata();
		}
	}
}
int main(){
	while (scanf("%d",&n)==1){
		FORP(i,1,n)
			FORP(j,1,n) {
				scanf("%d",&w[i][j]); 
		}
		KM();
		int ans=0;
		FORP(i,1,n) if (link[i]) //计算边权和
			ans+=w[link[i]][i];
		printf("%d\n",ans);
	}
}

 

HDU 2255 & KM模板

标签:

原文地址:http://www.cnblogs.com/YCuangWhen/p/5194215.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!