奔小康赚大钱 HDU - 2255(KM)

奔小康赚大钱

 HDU - 2255

题意:给出每个村民愿意为每个房子出的价钱,问怎么分配房子可以使收益最大。

KM算法

一直对slack数组有点迷~

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int inf=0x3f3f3f3f;
 4 const int maxn=310;
 5 int n;
 6 
 7 int c[maxn][maxn];
 8 int vg[maxn],vb[maxn];
 9 int eb[maxn],eg[maxn];
10 int mc[maxn];
11 int d;
12 
13 int dfs(int id){
14     vg[id]=1;
15     for(int i=0;i<n;i++){
16         if(vb[i]) continue;  //只能访问一次
17         int gap=eg[id]+eb[i]-c[id][i];
18         if(gap==0){  //有边
19             vb[i]=1;
20             if(mc[i]==-1||dfs(mc[i])){
21                 mc[i]=id;
22                 return 1;
23             }
24         }else{
25             d=min(d,gap);  //该男最少还需要的期望值
26         }
27     }
28     return 0;
29 }
30 
31 void KM(){
32     memset(mc,-1,sizeof(mc));
33     memset(eb,0,sizeof(eb));
34     for(int i=0;i<n;i++){
35         eg[i]=c[i][0];
36         for(int j=1;j<n;j++) eg[i]=max(c[i][j],eg[i]);
37     }
38     for(int i=0;i<n;i++){
39         while(1){
40             memset(vg,0,sizeof(vg));
41             memset(vb,0,sizeof(vb));
42             d=inf;
43             if(dfs(i)) break;
44             for(int i=0;i<n;i++){
45                 if(vg[i]) eg[i]-=d;
46                 if(vb[i]) eb[i]+=d;
47             }
48         }
49     }
50 }
51 
52 int main(){
53     while(scanf("%d",&n)!=EOF){
54         memset(c,0,sizeof(c));
55         for(int i=0;i<n;i++)
56             for(int j=0;j<n;j++)
57             scanf("%d",&c[i][j]);
58         KM();
59         int ans=0;
60         for(int i=0;i<n;i++) ans+=c[mc[i]][i];
61         printf("%d\n",ans);
62     }
63 
64 }
无slack
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int inf=0x3f3f3f3f;
 4 const int maxn=310;
 5 int n;
 6 
 7 int c[maxn][maxn];
 8 int vg[maxn],vb[maxn];
 9 int eb[maxn],eg[maxn];
10 int mc[maxn];
11 int slack[maxn];
12 
13 int dfs(int id){
14     vg[id]=1;
15     for(int i=0;i<n;i++){
16         if(vb[i]) continue;  //只能访问一次
17         int gap=eg[id]+eb[i]-c[id][i];
18         if(gap==0){  //有边
19             vb[i]=1;
20             if(mc[i]==-1||dfs(mc[i])){
21                 mc[i]=id;
22                 return 1;
23             }
24         }else{
25             slack[i]=min(slack[i],gap);  //该男最少还需要的期望值
26         }
27     }
28     return 0;
29 }
30 
31 void KM(){
32     memset(mc,-1,sizeof(mc));
33     memset(eb,0,sizeof(eb));
34     for(int i=0;i<n;i++){
35         eg[i]=c[i][0];
36         for(int j=1;j<n;j++) eg[i]=max(c[i][j],eg[i]);
37     }
38     for(int i=0;i<n;i++){
39         memset(slack,inf,sizeof(slack));
40         while(1){
41             memset(vg,0,sizeof(vg));
42             memset(vb,0,sizeof(vb));
43             if(dfs(i)) break;
44             int d=inf;
45             for(int i=0;i<n;i++) if(!vb[i]) d=min(d,slack[i]);
46             for(int i=0;i<n;i++){
47                 if(vg[i]) eg[i]-=d;
48                 if(vb[i]) eb[i]+=d;
49                 else slack[i]-=d;
50             }
51         }
52     }
53 }
54 
55 int main(){
56     while(scanf("%d",&n)!=EOF){
57         memset(c,0,sizeof(c));
58         for(int i=0;i<n;i++)
59             for(int j=0;j<n;j++)
60             scanf("%d",&c[i][j]);
61         KM();
62         int ans=0;
63         for(int i=0;i<n;i++) ans+=c[mc[i]][i];
64         printf("%d\n",ans);
65     }
66     return 0;
67 }
slack

 

posted @ 2017-08-18 14:12  yijiull  阅读(218)  评论(0编辑  收藏  举报