HDU2255(KB10-K 二分图最大权匹配)

奔小康赚大钱

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


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

 
 1 //2017-08-21
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 const int N = 310;
10 const int INF = 0x3f3f3f3f;
11 int G[N][N];
12 int n_x, n_y;
13 int matching[N], l_x[N], l_y[N];
14 int slack[N];
15 bool vis_x[N], vis_y[N];
16 
17 bool dfs(int u){
18     vis_x[u] = 1;
19     for(int v = 0; v < n_y; v++){
20         if(vis_y[v])continue;
21         int tmp = l_x[u]+l_y[v]-G[u][v];
22         if(tmp == 0){
23             vis_y[v] = 1;
24             if(matching[v] == -1 || dfs(matching[v])){
25                 matching[v] = u;
26                 return true;
27             }
28         }else if(slack[v] > tmp){
29             slack[v] = tmp;
30         }
31     }
32     return false;
33 }
34 
35 int KM(){
36     memset(matching, -1, sizeof(matching));
37     memset(l_y, 0, sizeof(l_y));
38     for(int u = 0; u < n_x; u++){
39         l_x[u] = -INF;
40         for(int v = 0; v < n_y; v++)
41             if(G[u][v] > l_x[u])
42                   l_x[u] = G[u][v];
43     }
44     for(int u = 0; u < n_x; u++){
45         for(int i = 0; i < n_y; i++)
46               slack[i] = INF;
47         while(1){
48             memset(vis_x, 0, sizeof(vis_x));
49             memset(vis_y, 0, sizeof(vis_y));
50             if(dfs(u))break;
51             int d = INF;
52             for(int i = 0; i < n_y; i++)
53                   if(!vis_y[i] && d > slack[i])
54                       d = slack[i];
55             for(int i = 0; i < n_x; i++)
56                   if(vis_x[i])
57                       l_x[i] -= d;
58             for(int i = 0; i < n_y; i++){
59                 if(vis_y[i])l_y[i] += d;
60                 else slack[i] -= d;
61             }
62         }
63     }
64     int ans = 0;
65     for(int i = 0; i < n_y; i++)
66         if(matching[i] != -1)
67               ans += G[matching[i]][i];
68     return ans;
69 }
70 
71 int main()
72 {
73     freopen("inputK.txt", "r", stdin);
74     int n;
75     while(scanf("%d", &n)!=EOF){
76         for(int i = 0; i < n; i++){
77             for(int j = 0; j < n; j++){
78                 scanf("%d", &G[i][j]);
79             }
80         }
81         n_x = n_y = n;
82         printf("%d
", KM());
83     }
84 
85     return 0;
86 }
原文地址:https://www.cnblogs.com/Penn000/p/7406240.html