码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 2255 奔小康赚大钱

时间:2018-07-14 16:24:08      阅读:101      评论:0      收藏:0      [点我收藏+]

标签:ack   splay   ++   取反   closed   匹配   php   stdout   hdu   

hdu 2255

费用流的模板题。

就是用KM跑一下最优匹配就好了。

代码:

技术分享图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
 4 #define LL long long
 5 #define ULL unsigned LL
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define lson l,m,rt<<1
10 #define rson m+1,r,rt<<1|1
11 #define max3(a,b,c) max(a,max(b,c))
12 #define min3(a,b,c) min(a,min(b,c))
13 typedef pair<int,int> pll;
14 const int inf = 0x3f3f3f3f;
15 const LL INF = 0x3f3f3f3f3f3f3f3f;
16 const LL mod =  (int)1e9+7;
17 const int N = 310;
18 int val[N][N];
19 int lx[N], ly[N], match[N];
20 int visx[N], visy[N];
21 int slack[N];
22 int n;
23 void init(){
24     memset(match, -1, sizeof(match));
25     memset(ly, 0, sizeof(ly));
26     memset(lx, -inf, sizeof(lx));
27 }
28 bool hunger(int u){
29     visx[u] = 1;
30     for(int i = 1; i <= n; i++){
31         if(visy[i]) continue;
32         else {
33             if(lx[u] + ly[i] == val[u][i]){
34                 visy[i] = 1;
35                 if(match[i] == -1 || hunger(match[i])){
36                     match[i] = u;
37                     return true;
38                 }
39             }
40             else slack[i] = min(slack[i], lx[u]+ly[i] - val[u][i]);
41         }
42     }
43     return false;
44 
45 }
46 void KM_perferct_match(){
47     for(int i = 1; i <= n; i++)
48         for(int j = 1; j <= n; j++)
49             lx[i] = max(lx[i], val[i][j]);
50     for(int i = 1; i <= n; i++){
51         memset(slack, inf, sizeof(slack));
52         while(1){
53             memset(visx, 0, sizeof(visx));
54             memset(visy, 0, sizeof(visy));
55             if(hunger(i)) break;
56             else {
57                 int tmp = inf;
58                 for(int j = 1; j <= n; j++)
59                     if(!visy[j]) tmp = min(tmp, slack[j]);
60                 ///if(tmp == inf) break;
61                 for(int j = 1; j <= n; j++){
62                     if(visx[j]) lx[j] -= tmp;
63                     if(visy[j]) ly[j] += tmp;
64                     else slack[j] -= tmp;
65                 }
66             }
67         }
68     }
69 }
70 int main(){
71 
72     while(~scanf("%d", &n)){
73         init();
74         for(int i = 1; i <= n; i++)
75             for(int j = 1; j <= n; j++)
76                 scanf("%d", &val[i][j]);
77         KM_perferct_match();
78         int ans = 0;
79         for(int i = 1; i <= n; i++){
80             if(match[i] != -1) ans += val[match[i]][i];
81         }
82         printf("%d\n", ans);
83     }
84     return 0;
85 }
View Code

 注意的就是在这个跑法中,得到的结果是最大匹配的最大值是多少。

如果要求最小值的话,将值取反,变成负数,然后再套模板,跑出结果,最后再取反就是最小值了。

HDU 2255 奔小康赚大钱

标签:ack   splay   ++   取反   closed   匹配   php   stdout   hdu   

原文地址:https://www.cnblogs.com/MingSD/p/9309648.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!