HDU2255 奔小康賺大錢【二分圖 帶權最優匹配】
阿新 • • 發佈:2018-12-01
奔小康賺大錢
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 14706 Accepted Submission(s): 6394
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
問題連結:HDU2255 奔小康賺大錢
解題思路:二分圖帶權最優匹配模板題,KM演算法
AC的C++程式:
#include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N=305; const int INF=0x3f3f3f3f; //girl表示村民,boy表示房子 int love[N][N]; int ex_girl[N]; int ex_boy[N]; bool vis_girl[N]; bool vis_boy[N]; int match[N]; int slack[N]; int n; bool dfs(int girl) { vis_girl[girl]=true; for(int boy=0;boy<n;boy++) { if(vis_boy[boy]) continue; int gap=ex_girl[girl]+ex_boy[boy]-love[girl][boy]; if(gap==0)//符合條件 { vis_boy[boy]=true; if(match[boy]==-1||dfs(match[boy])) { match[boy]=girl; return true; } } else slack[boy]=min(slack[boy],gap); } return false; } int KM() { memset(match,-1,sizeof(match)); memset(ex_boy,0,sizeof(ex_boy)); for(int i=0;i<n;i++) { ex_girl[i]=love[i][0]; for(int j=1;j<n;j++) ex_girl[i]=max(ex_girl[i],love[i][j]); } for(int i=0;i<n;i++) { memset(slack,INF,sizeof(slack)); for(;;) { memset(vis_boy,false,sizeof(vis_boy)); memset(vis_girl,false,sizeof(vis_girl)); if(dfs(i)) break; int d=INF; for(int j=0;j<n;j++) if(!vis_boy[j]) d=min(d,slack[j]); for(int j=0;j<n;j++) { if(vis_girl[j]) ex_girl[j]-=d; if(vis_boy[j]) ex_boy[j]+=d; else slack[j]-=d; } } } //匹配完成 int res=0; for(int i=0;i<n;i++) res+=love[match[i]][i]; return res; } int main() { while(~scanf("%d",&n)) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&love[i][j]); printf("%d\n",KM()); } return 0; }