HDU 2255 & KM模板

题意:

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

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);
	}
}
时间: 2024-10-13 00:13:46

HDU 2255 & KM模板的相关文章

hdu 2255(KM算法模板)

奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3707    Accepted Submission(s): 1618 Problem Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考

hdu 2255奔小康赚大钱 KM算法模板

题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=2255 一,KM算法:(借助这个题写一下个人对km的理解与km模板) KM算法主要是用来求解图的最优匹配的. 1.带权二分图:  在二分图中每一条边(x.y)相应一个权值Wi这样的二分图叫带权二分图. 一个匹配的权值就是该匹配中全部边的权值之和. 2,最优匹配: 权值最大的一个完美匹配.叫做最优匹配.       <km算法思想> 对于一个带权全然二分图:G(V.E),对于当中每一条边(x.y)边

hdu 2255 二分图带权匹配 模板题

模板+注解在 http://blog.csdn.net/u011026968/article/details/38276945 hdu 2255 代码: //KM×î´ó×îСƥÅä #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; #define INF 0x0fffffff const int MAXN

HDU 2255 ——奔小康赚大钱——————【KM算法裸题】

奔小康赚大钱 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2255 Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到

hdu 2255 奔小康赚大钱(KM算法)

奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3248    Accepted Submission(s): 1413 Problem Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子. 这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考

hdu 2255 二分图最大权匹配 *

题意:说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子.另 一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格, 比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出2

KM模板

HDU 2255 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 306 int n,e[N][N]; int match[N],slack[N],ea[N],eb[N]; bool va[N],vb[N]; bool dfs(int u) { va[u]=true; int gap; for(in

Saving Princess claire_(hdu 4308 bfs模板题)

http://acm.hdu.edu.cn/showproblem.php?pid=4308 Saving Princess claire_ Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2305    Accepted Submission(s): 822 Problem Description Princess claire_ wa

hdu 4862 KM算法 最小K路径覆盖的模型

http://acm.hdu.edu.cn/showproblem.php?pid=4862 选t<=k次,t条路要经过所有的点一次并且仅仅一次, 建图是问题: 我自己最初就把n*m 个点分别放入X集合以及Y集合,再求最优匹配,然后连样例都过不了,而且其实当时解释不了什么情况下不能得到结果,因为k此这个条件相当于没用上... 建图方法: 1.X集合和Y集合都放入n*m+k个点,X中前n*m个点和Y中前n*m个点之间,如果格子里的值相等,权就是(收益-耗费),不等就是(-耗费),因为要的是最大收益