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万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
 
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 }

 

posted @ 2013-08-25 21:45  ゐ星落★孤晨ね  阅读(189)  评论(0编辑  收藏  举报