zoukankan      html  css  js  c++  java
  • hdu 2255 带权最大匹配 km算法

    奔小康赚大钱

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2350    Accepted Submission(s): 1028


    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
     
    Recommend
    lcy
     
    很裸的km算法,求完美匹配下的最大匹配,模板题,详见代码:
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    
    #define LL long long
    #define ULL unsigned long long
    #define UINT unsigned int
    #define MAX_INT 0x7fffffff
    #define MAX_LL 0x7fffffffffffffff
    #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
    #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
    
    #define MAXN 305
    #define INF MAX_INT
    
    int lx[MAXN], ly[MAXN], slack[MAXN];
    int w[MAXN][MAXN], ytox[MAXN];
    int s[MAXN], t[MAXN];
    int n;
    
    int km(int u){
        int v, tmp;
        s[u]=1;
        for(v=1; v<=n; v++){
            if(t[v]) continue;
            tmp=lx[u]+ly[v]-w[u][v];
            if(!tmp){                           //在相等子图中
                t[v]=1;
                if(-1 == ytox[v] || km(ytox[v])){       //找到未匹配点
                    ytox[v]=u;
                    return 1;
                }
            }
            else slack[v]=MIN(slack[v], tmp);           //不属于t集合的松弛值更新。
        }
        return 0;
    }
    
    int solve(){
        int i,j,ans=0, tmp;
        memset(ly, 0, sizeof(ly));
        memset(lx, 0, sizeof(lx));
        memset(ytox, -1, sizeof(ytox));
        for(i=1; i<=n; i++){
            for(j=1; j<=n; j++)                 
                lx[i]=MAX(lx[i], w[i][j]);          //初始化lx为相邻边中最大边权
        }
    
        for(i=1; i<=n; i++){
            for(j=1; j<=n; j++) slack[j]=INF;       //每次增广前初始化slack
            while(1){
                memset(s, 0, sizeof(s));            //交错树(dfs中的增广树)初始集合为空
                memset(t, 0, sizeof(t));
    
                if(km(i)) break;
                tmp=INF;
                for(j=1; j<=n; j++) if(!t[j])
                    tmp=MIN(tmp, slack[j]);         //lx[i]+ly[j]-w[i][j]的最小差值
                for(j=1; j<=n; j++) if(s[j])
                    lx[j]-=tmp;                     //
                for(j=1; j<=n; j++){
                    if(t[j]) ly[j]+=tmp;
                    //else slack[j]-=tmp;           //这里不更新slack值也该可以,因为接下来会在dfs中更新
                }
            }
        }
        ans=0;
        for(i=1; i<=n; i++) ans+=w[ytox[i]][i];
        return ans;
    }
    
    int main(){
        //freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
        while(scanf(" %d", &n)==1){
            int i,j,ans;
            for(i=1; i<=n; i++){
                for(j=1; j<=n; j++)
                    scanf(" %d", &w[i][j]);
            }
            ans=solve();
            printf("%d
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    服务部署 RPC vs RESTful
    模拟浏览器之从 Selenium 到splinter
    windows程序设计 vs2012 新建win32项目
    ubuntu python 安装numpy,scipy.pandas.....
    vmvare 将主机的文件复制到虚拟机系统中 安装WMware tools
    ubuntu 修改root密码
    python 定义类 简单使用
    python 定义函数 两个文件调用函数
    python 定义函数 调用函数
    python windows 安装gensim
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3318311.html
Copyright © 2011-2022 走看看