zoukankan      html  css  js  c++  java
  • hdu-2255 D

    question:

    传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。
    这可是一件大事,关系到人民的住房问题啊。村里共有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算法,直接套用模板
    #include <cstring>
    #include <cstdio>
    #include<algorithm> 
    using namespace std;
    const int MAXN = 305;
    const int INF = 0x3f3f3f3f;
    int qiwang[MAXN][MAXN];   // 记录每个村民对房屋的价值 
    int cunmin[MAXN];      
    int fangwu[MAXN];       
    bool vis_cunmin[MAXN];    // 记录每一轮匹配过的村民 
    bool vis_fangwu[MAXN];     // 记录每一轮匹配过的房屋 
    int match[MAXN];        
    int slack[MAXN];       
    
    int N;
    
    
    bool dfs(int cm)
    {
        vis_cunmin[cm] = true;
    
        for (int fw = 0; fw < N; ++fw) {
    
            if (vis_fangwu[fw]) continue; // 每一轮匹配 每个房屋只尝试一次 
    
            int gap = cunmin[cm] + fangwu[fw] - qiwang[cm][fw];
    
            if (gap == 0) {  // 如果符合要求
                vis_fangwu[fw] = true;
                if (match[fw] == -1 || dfs( match[fw] )) {    // 找到一个没有匹配的房屋 或者该房屋的村民可以找到其他房屋 
                    match[fw] = cm;
                    return true;
                }
            } else {
                slack[fw] = min(slack[fw], gap);  
            }
        }
    
        return false;
    }
    
    int KM()
    {
        memset(match, -1, sizeof match);    // 初始每个房屋都没有匹配的村民
        memset(fangwu, 0, sizeof fangwu);  
    
        // 每个村民对房屋的价值 
        for (int i = 0; i < N; ++i) {
            cunmin[i] = qiwang[i][0];
            for (int j = 1; j < N; ++j) {
                cunmin[i] = max(cunmin[i], qiwang[i][j]);
            }
        }
    
        // 尝试为每一个村民解决房屋问题
        for (int i = 0; i < N; ++i) {
    
            fill(slack, slack + N, INF);    
    
            while (1) {
                memset(vis_cunmin, false, sizeof vis_cunmin);
                memset(vis_fangwu, false, sizeof vis_fangwu);
    
                if (dfs(i)) break;  // 找到房屋,退出 
                int d = INF;
                for (int j = 0; j < N; ++j)
                    if (!vis_fangwu[j]) d = min(d, slack[j]);
                for (int j = 0; j < N; ++j) {
                    if (vis_cunmin[j]) cunmin[j] -= d;
                    if (vis_fangwu[j]) fangwu[j] += d;
                    else slack[j] -= d;
                }
            }
        }
    
        // 匹配完成 求出所有配对的收入的和
        int res = 0;
        for (int i = 0; i < N; ++i)
            res += qiwang[ match[i] ][i];
        return res;
    }
    int main()
    {
        while (~scanf("%d", &N)) {
    
            for (int i = 0; i < N; ++i)
                for (int j = 0; j < N; ++j)
                    scanf("%d", &qiwang[i][j]);
            printf("%d
    ", KM());
        }
        return 0;
    }        


  • 相关阅读:
    Javascript构造函数的继承
    什么数据库能抗住《王者荣耀》的1亿DAU?
    支持微信支付亿级请求的TBase数据库大揭秘
    我在MySQL的那些年(一)
    谁是银行核心数据库的破局者?
    X侦探所事件薄 | 一次内存溢出之谜
    腾讯云数据库新生代产品获国家级认证
    POJ 2594 传递闭包的最小路径覆盖
    POJ 1719 二分图最大匹配(记录路径)
    HDU 1533 KM算法(权值最小的最佳匹配)
  • 原文地址:https://www.cnblogs.com/hrlsm/p/13382872.html
Copyright © 2011-2022 走看看