• 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;
    }        


  • 相关阅读:
    【Oracle 12c】最新CUUG OCP-071考试题库(58题)
    【Oracle 12c】最新CUUG OCP-071考试题库(57题)
    【Oracle 12c】最新CUUG OCP-071考试题库(56题)
    【Oracle 12c】最新CUUG OCP-071考试题库(55题)
    voip,
    处理xmpp 离线信息,
    流程,xmpp发送信息,
    折腾我几天的 消息状态,
    三者的区别,
    bundle,
  • 原文地址:https://www.cnblogs.com/hrlsm/p/13382872.html
Copyright © 2020-2023  润新知