HDU2255:奔小康賺大錢

點擊打開題目鏈接

奔小康賺大錢

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


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
 

Recommend
lcy
 


=====================================算法分析=====================================


裸二分圖最佳完美匹配。


=======================================代碼=======================================




#include<stdio.h>
#include<string.h>

#define MIN(A,B)  ((A)<(B)?(A):(B))
#define MAX(A,B)  ((A)>(B)?(A):(B))

const int INF1=0x7f;
const int INF4=0x7f7f7f7f;
const int MAXN=305;

int N,Edge[MAXN][MAXN],Linker[MAXN];

int TopX[MAXN],TopY[MAXN],Slack[MAXN];

bool VisX[MAXN],VisY[MAXN];

bool DFS(int X)
{
	VisX[X]=true;
	for(int y=1;y<=N;++y) if(!VisY[y])
	{
		int slacklen=TopX[X]+TopY[y]-Edge[X][y];
		if(slacklen)
		{
			Slack[y]=MIN(Slack[y],slacklen);
		}
		else
		{
			VisY[y]=true;
			if(Linker[y]==-1||DFS(Linker[y]))
			{
				Linker[y]=X;  
				return true;
			}
		}
	}
	return false;
}

void UpdateTop()
{
	int addconst=INF4;
	for(int y=1;y<=N;++y)
	{ 
		if(!VisY[y]) { addconst=MIN(addconst,Slack[y]); }
	}
	for(int i=1;i<=N;++i)
	{
		if(VisX[i])  { TopX[i]-=addconst; }
		if(VisY[i])  { TopY[i]+=addconst; }
		if(!VisY[i]) { Slack[i]-=addconst; } 
	}
}

int KM()
{
	memset(TopX,0,sizeof(TopX));
	memset(TopY,0,sizeof(TopY));
	memset(Linker,-1,sizeof(Linker));
	for(int x=1;x<=N;++x)
	{
		for(int y=1;y<=N;++y)
		{
			TopX[x]=MAX(TopX[x],Edge[x][y]);
		}
	}
	for(int x=1;x<=N;++x) while(1)
	{
		memset(VisX,0,sizeof(VisX));
		memset(VisY,0,sizeof(VisY));
		memset(Slack,INF1,sizeof(Slack));
		if(DFS(x)) { break; }
		else { UpdateTop(); }
	}
	int sum=0;
	for(int i=1;i<=N;++i)
	{
		sum+=TopX[i];
		sum+=TopY[i];
	}
	return sum;
}

int main()
{
	while(scanf("%d",&N)==1)
	{
		for(int i=1;i<=N;++i)
		{
			for(int j=1;j<=N;++j)
			{
				scanf("%d",&Edge[i][j]);
			}
		}
		printf("%d\n",KM());
	}
	return 0;
}

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