HDU2255奔小康賺大錢

http://acm.hdu.edu.cn/showproblem.php?pid=2255

奔小康賺大錢

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 17692    Accepted Submission(s): 7450


 

Problem Description

傳說在遙遠的地方有一個非常富裕的村落,有一天,村長決定進行制度改革:重新分配房子。
這可是一件大事,關係到人民的住房問題啊。村裏共有n間房間,剛好有n家老百姓,考慮到每家都要有房住(如果有老百姓沒房子住的話,容易引起不安定因素),每家必須分配到一間房子且只能得到一間房子。
另一方面,村長和另外的村領導希望得到最大的效益,這樣村裏的機構纔會有錢.由於老百姓都比較富裕,他們都能對每一間房子在他們的經濟範圍內出一定的價格,比如有3間房子,一家老百姓可以對第一間出10萬,對第2間出2萬,對第3間出20萬.(當然是在他們的經濟範圍內).現在這個問題就是村領導怎樣分配房子才能使收入最大.(村民即使有錢購買一間房子但不一定能買到,要看村領導分配的).

 

 

Input

輸入數據包含多組測試用例,每組數據的第一行輸入n,表示房子的數量(也是老百姓家的數量),接下來有n行,每行n個數表示第i個村名對第j間房出的價格(n<=300)。

 

 

Output

請對每組數據輸出最大的收入值,每組的輸出佔一行。
 

 

 

Sample Input


 

2 100 10 15 23

 

 

Sample Output


 

123

 

 

Source

HDOJ 2008 Summer Exercise(4)- Buffet Dinner

 

 

Recommend

lcy

 

二分圖最大權分配板子,關於二分圖的講解在另一篇博客(未完成)。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=310;
int n,v[N][N],exa[N],exb[N];//v存邊權,exa是a的點權,exb是b的點權
int con[N];//存b匹配的a(而不是a匹配的b,在給a配對時,是判斷b是否已經被匹配)
bool visa[N],visb[N];//增廣路中的a,b 
int slack[N];//每次減去的d
bool dfs(int a)
{
	visa[a]=1;
	for(int b=1;b<=n;b++)
	{
		if(visb[b])
			continue;
		int gap=exa[a]+exb[b]-v[a][b];
		if(gap==0)
		{
			visb[b]=1;
			if(!con[b]||dfs(con[b]))
			{
				con[b]=a;
				return true;
			}
		}
		else
			slack[b]=min(slack[b],gap);
	}
	return false;
}
int km()
{
	mem(con,0);
	for(int i=1;i<=n;i++)
	{ 
		mem(slack,INF);
		while(1)
		{
			mem(visa,0);
			mem(visb,0);
			if(dfs(i))
				break;
			int d=INF;
			for(int j=1;j<=n;j++)
				if(!visb[j])
					d=min(d,slack[j]);
			for(int j=1;j<=n;j++)
			{
				if(visa[j])
					exa[j]-=d;
				if(visb[j])
					exb[j]+=d;
				else
					slack[j]-=d;
			}
		}
	}
	int res=0;
	for(int i=1;i<=n;i++)
		res+=v[con[i]][i];
	return res;
	
}
int main()
{
	while(~scanf("%d",&n))
	{
		mem(v,0);
		mem(exa,0);
		mem(exb,0);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
			{
				scanf("%d",&v[i][j]);
				exa[i]=max(exa[i],v[i][j]);
			}
		printf("%d\n",km());
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章