奔小康赚大钱
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5029 Accepted Submission(s): 2160
Problem Description
传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。
这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。
另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
这可是一件大事,关系到人民的住房问题啊。村里共有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
解题:最大权匹配,最佳完美匹配
1 #include <bits/stdc++.h> 2 #define type int 3 using namespace std; 4 const int INF = 0x3f3f3f3f; 5 const int maxn = 310; 6 type Lx[maxn],Ly[maxn],W[maxn][maxn],slack[maxn]; 7 bool S[maxn],T[maxn]; 8 int n,Link[maxn]; 9 bool match(int u) { 10 S[u] = true; 11 for(int v = 0; v < n; ++v) { 12 if(T[v]) continue; 13 type d = Lx[u] + Ly[v] - W[u][v]; 14 if(!d) { //浮点数时需要用精度判0 15 T[v] = true; 16 if(Link[v] == -1 || match(Link[v])) { 17 Link[v] = u; 18 return true; 19 } 20 } else if(slack[v] > d) slack[v] = d; 21 } 22 return false; 23 } 24 void update() { 25 type d = INF; 26 for(int i = 0; i < n; ++i) 27 if(!T[i] && slack[i] < d) 28 d = slack[i]; 29 for(int i = 0; i < n; ++i) { 30 if(S[i]) Lx[i] -= d; 31 if(T[i]) Ly[i] += d; 32 else slack[i] -= d; 33 } 34 } 35 type KuhnMunkras() { 36 for(int u = 0; u < n; ++u) { 37 Lx[u] = -INF; 38 Ly[u] = 0; 39 Link[u] = -1; 40 for(int v = 0; v < n; ++v) 41 Lx[u] = max(Lx[u],W[u][v]); 42 } 43 for(int u = 0; u < n; ++u){ 44 for(int v = 0; v < n; ++v) slack[v] = INF; 45 while(true){ 46 memset(S,false,sizeof S); 47 memset(T,false,sizeof T); 48 if(match(u)) break; 49 update(); 50 } 51 } 52 type ret = 0; 53 for(int i = 0; i < n; ++i) 54 if(Link[i] > -1) ret += W[Link[i]][i]; 55 return ret; 56 } 57 int main() { 58 while(~scanf("%d",&n)) { 59 memset(W,0,sizeof W); 60 for(int i = 0; i < n; ++i) 61 for(int j = 0; j < n; ++j) 62 scanf("%d",W[i] + j); 63 printf("%d ",KuhnMunkras()); 64 } 65 return 0; 66 }