奔小康赚大钱
题意:给出每个村民愿意为每个房子出的价钱,问怎么分配房子可以使收益最大。
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 ",ans); 62 } 63 64 }

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 ",ans); 65 } 66 return 0; 67 }