hdu 2255 奔小康赚大钱 (KM算法)
题目链接:奔小康赚大钱
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2283 Accepted Submission(s): 1006
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
本题题意很简单,同时也是一个最佳匹配的问题,于是这就让我们想起啦KM算法,我也是看啦别人的模板,然后直接按这模板打出来,就可以把这题给AC掉。
1 #include<stdio.h> 2 #include<string.h> 3 #define INF 0xfffffff 4 int n; 5 int map[305][305],lx[305],ly[305],link[305]; 6 int vx[305],vy[305],s[305]; 7 int path(int x) //匈牙利算法找最大匹配 8 { 9 vx[x]=1; 10 for(int y=1;y<=n;y++) 11 { 12 if(vy[y]) continue; 13 int tmp=lx[x]+ly[y]-map[x][y]; 14 if(tmp==0) 15 { 16 vy[y]=1; 17 if(link[y]==-1||path(link[y])) 18 { 19 link[y]=x; 20 return 1; 21 } 22 } 23 else if(tmp<s[y]) 24 { 25 s[y]=tmp; 26 } 27 } 28 return 0; 29 } 30 int KM() 31 { 32 int i,x; 33 memset(link,-1,sizeof(link)); 34 for(x=1;x<=n;x++) 35 { 36 for(i=1;i<=n;i++) 37 { 38 s[i]=INF; 39 } 40 while(1) 41 { 42 memset(vx,0,sizeof(vx)); 43 memset(vy,0,sizeof(vy)); 44 if(path(x)) 45 break; 46 int d=INF; 47 for(i=1;i<=n;i++) 48 { 49 if(!vy[i]&&d>s[i]) 50 { 51 d=s[i]; 52 } 53 } 54 for(i=1;i<=n;i++) 55 { 56 if(vx[i]) 57 { 58 lx[i]-=d; 59 } 60 } 61 for(i=1;i<=n;i++) 62 { 63 if(vy[i]) 64 { 65 ly[i]+=d; 66 } 67 else 68 { 69 s[i]-=d; 70 } 71 } 72 } 73 } 74 int res=0; 75 for(i=1;i<=n;i++) 76 { 77 if(link[i]!=-1) 78 { 79 res+=map[link[i]][i]; 80 } 81 } 82 return res; 83 } 84 int main() 85 { 86 int i,j; 87 while(scanf("%d",&n)!=EOF) 88 { 89 memset(lx,0,sizeof(lx)); 90 memset(ly,0,sizeof(ly)); 91 for(i=1;i<=n;i++) 92 { 93 for(j=1;j<=n;j++) 94 { 95 scanf("%d",&map[i][j]); 96 if(map[i][j]>lx[i]) 97 { 98 lx[i]=map[i][j]; 99 } 100 } 101 } 102 int sum=KM(); 103 printf("%d\n",sum); 104 } 105 return 0; 106 }