zoukankan      html  css  js  c++  java
  • hdu-2255 奔小康赚大钱---KM模板

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=2255

    题目大意:

    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
     
    解题思路:
    KM算法模板:
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<map>
     6 using namespace std;
     7 typedef long long ll;
     8 const int maxn = 300 + 10;
     9 const int INF = 0x3f3f3f3f;
    10 
    11 int wx[maxn], wy[maxn];//每个点的顶标值(需要根据二分图处理出来)
    12 int cx[maxn], cy[maxn];//每个点所匹配的点
    13 int visx[maxn], visy[maxn];//每个点是否加入增广路
    14 int cntx, cnty;//分别是X和Y的点数
    15 int Map[maxn][maxn];//二分图边的权值
    16 int minz;//边权和顶标最小的差值
    17 
    18 bool dfs(int u)//进入DFS的都是X部的点
    19 {
    20     visx[u] = 1;//标记进入增广路
    21     for(int v = 1; v <= cnty; v++)
    22     {
    23         if(!visy[v] && Map[u][v] != INF)//如果Y部的点还没进入增广路,并且存在路径
    24         {
    25             int t = wx[u] + wy[v] - Map[u][v];
    26             if(t == 0)//t为0说明是相等子图
    27             {
    28                 visy[v] = 1;//加入增广路
    29 
    30                 //如果Y部的点还未进行匹配
    31                 //或者已经进行了匹配,可以从原来的匹配反向找到增广路
    32                 //那就可以进行匹配
    33                 if(cy[v] == -1 || dfs(cy[v]))
    34                 {
    35                     cx[u] = v;
    36                     cy[v] = u;//进行匹配
    37                     return 1;
    38                 }
    39             }
    40             else if(t > 0)//此处t一定是大于0,因为顶标之和一定>=边权
    41             {
    42                 minz = min(minz, t);//边权和顶标最小的差值
    43             }
    44         }
    45     }
    46     return false;
    47 }
    48 
    49 int KM()
    50 {
    51     memset(cx, -1, sizeof(cx));
    52     memset(cy, -1, sizeof(cy));
    53     memset(wx, 0, sizeof(wx));//wx的顶标为该点连接的边的最大权值
    54     memset(wy, 0, sizeof(wy));//wy的顶标为0
    55     for(int i = 1; i <= cntx; i++)//预处理出顶标值
    56     {
    57         for(int j = 1; j <= cnty; j++)
    58         {
    59             if(Map[i][j] == INF)continue;
    60             wx[i] = max(wx[i], Map[i][j]);
    61         }
    62     }
    63     for(int i = 1; i <= cntx; i++)//枚举X部的点
    64     {
    65         while(1)
    66         {
    67             minz = INF;
    68             memset(visx, 0, sizeof(visx));
    69             memset(visy, 0, sizeof(visy));
    70             if(dfs(i))break;//已经匹配正确
    71 
    72             //还未匹配,将X部的顶标减去minz,Y部的顶标加上minz
    73             for(int j = 1; j <= cntx; j++)
    74                 if(visx[j])wx[j] -= minz;
    75             for(int j = 1; j <= cnty; j++)
    76                 if(visy[j])wy[j] += minz;
    77         }
    78     }
    79 
    80     int ans = 0;//二分图最优匹配权值
    81     for(int i = 1; i <= cntx; i++)
    82         if(cx[i] != -1)ans += Map[i][cx[i]];
    83     return ans;
    84 }
    85 int n, k;
    86 int main()
    87 {
    88     while(scanf("%d", &n) != EOF)
    89     {
    90         for(int i = 1; i <= n; i++)
    91         {
    92             for(int j = 1; j <= n; j++)
    93                 scanf("%d", &Map[i][j]);
    94         }
    95         cntx = cnty = n;
    96         printf("%d
    ", KM());
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    vscode的插件收集
    关于vue移动端的适配
    Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null objec
    android studio 使用 aidl(三)权限验证
    Android权限级别(protectionLevel)
    android studio 使用 aidl(二)异步回调
    android studio 使用 aidl(一)基础用法
    如何获取Android唯一标识(唯一序列号)
    android studio 生成aar和引用aar
    android studio 编译NDK android studio 生成.so文件
  • 原文地址:https://www.cnblogs.com/fzl194/p/8848071.html
Copyright © 2011-2022 走看看