zoukankan      html  css  js  c++  java
  • HDU2255 奔小康赚小钱钱(二分图-最大带权匹配)

    传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。 
    这可是一件大事,关系到人民的住房问题啊。村里共有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
    题解:二分图的最大带权匹配模板题:理解匈牙利算法(或KM算法)模板即可过;
    参考代码(KM算法优化后的,时间复杂度 O(n^3),可以作为模板):
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAXN = 305;
     4 const int INF = 0x3f3f3f3f;
     5 int love[MAXN][MAXN];   
     6 int ex_girl[MAXN],ex_boy[MAXN];       
     7 bool vis_girl[MAXN],vis_boy[MAXN];     
     8 int match[MAXN],slack[MAXN];       
     9 int N;
    10 
    11 bool dfs(int girl)
    12 {
    13     vis_girl[girl]=true;
    14     for(int boy=0;boy<N;++boy) 
    15     {
    16         if(vis_boy[boy]) continue;
    17         int gap=ex_girl[girl]+ex_boy[boy]-love[girl][boy];
    18         if(gap == 0) 
    19         { 
    20             vis_boy[boy] = true;
    21             if (match[boy] == -1 || dfs( match[boy] )) 
    22             {    
    23                 match[boy] = girl;
    24                 return true;
    25             }
    26         }
    27         else slack[boy] = min(slack[boy], gap);  
    28     }
    29     return false;
    30 }
    31 
    32 int KM()
    33 {
    34     memset(match,-1,sizeof match);    
    35     memset(ex_boy,0,sizeof ex_boy);  
    36     for(int i=0;i<N;++i) 
    37     {
    38         ex_girl[i]=love[i][0];
    39         for(int j=1;j<N;++j)  ex_girl[i]=max(ex_girl[i],love[i][j]);
    40     }
    41     for(int i=0;i<N;++i) 
    42     {
    43         fill(slack,slack+N,INF);    
    44         while(1)
    45         {
    46             memset(vis_girl,false,sizeof vis_girl);
    47             memset(vis_boy,false,sizeof vis_boy);
    48             if(dfs(i)) break;  
    49             int d=INF;
    50             for(int j=0;j<N;++j) if(!vis_boy[j]) d=min(d,slack[j]);
    51             for(int j=0;j<N;++j) 
    52             { 
    53                 if(vis_girl[j]) ex_girl[j]-=d;
    54                 if(vis_boy[j]) ex_boy[j]+=d;  
    55                 else slack[j]-=d;
    56             }
    57         }
    58     }
    59     int res=0;
    60     for(int i=0;i<N;++i) res+=love[match[i]][i];
    61     return res;
    62 }
    63 
    64 int main()
    65 {
    66     while(~scanf("%d", &N)) 
    67     {
    68         for(int i = 0; i < N; ++i)
    69             for(int j = 0; j < N; ++j)
    70                 scanf("%d", &love[i][j]);
    71         printf("%d
    ", KM());
    72     }
    73     return 0;
    74 }
    View Code
  • 相关阅读:
    第八周学习总结
    《程序是怎样跑起来的》第十一章
    第七周学习总结
    《程序是怎样跑起来的》第十章
    《程序是怎样跑起的》第九章
    第五周学习总结
    《程序是怎样跑起来的》第八章
    《程序是怎样跑起来的》第七章
    抽象类与接口学习总结
    多态学习总结
  • 原文地址:https://www.cnblogs.com/csushl/p/9520575.html
Copyright © 2011-2022 走看看