zoukankan      html  css  js  c++  java
  • hdu 2255 奔小康赚大钱 最大权匹配KM

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255

    传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子。
    这可是一件大事,关系到人民的住房问题啊。村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子。
    另一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出20万.(当然是在他们的经济范围内).现在这个问题就是村领导怎样分配房子才能使收入最大.(村民即使有钱购买一间房子但不一定能买到,要看村领导分配的).
     
    题意描述:由于此题为中文题,这里不作翻译。
    算法分析:最大权匹配问题,KM算法的入门题。百度KM算法有很多相关介绍的,这里不再累述。说明一点,KM优化:slack数组保存的是在dfs找增广路的时候随便求出Y集(二分图:X集和Y集)中不在相等子图中的每个y的值min(lx[x]-ly[y]-w[x][y]),最终算法复杂度为O(n^3)。
    对编译知识不是很了解,为什么这道题G++提交TLE而C++提交AC,感觉很厉害很高级的样子。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #define inf 0x7fffffff
    10 using namespace std;
    11 const int maxn=300+10;
    12 
    13 int n,nx,ny;
    14 int lx[maxn],ly[maxn],visx[maxn],visy[maxn];
    15 int link[maxn],slack[maxn];
    16 int w[maxn][maxn];
    17 
    18 int dfs(int x)
    19 {
    20     visx[x]=1;
    21     for (int y=1 ;y<=ny ;y++)
    22     {
    23         if (visy[y]) continue;
    24         int t=lx[x]+ly[y]-w[x][y];
    25         if (t==0)
    26         {
    27             visy[y]=1;
    28             if (link[y]==-1 || dfs(link[y]))
    29             {
    30                 link[y]=x;
    31                 return 1;
    32             }
    33         }
    34         else if (slack[y]>t) slack[y]=t;
    35     }
    36     return 0;
    37 }
    38 
    39 int KM()
    40 {
    41     memset(ly,0,sizeof(ly));
    42     memset(link,-1,sizeof(link));
    43     for (int x=1 ;x<=nx ;x++)
    44     {
    45         lx[x]=-inf;
    46         for (int y=1 ;y<=ny ;y++)
    47             lx[x]=max(lx[x],w[x][y]);
    48     }
    49     for (int x=1 ;x<=nx ;x++)
    50     {
    51         for (int j=1 ;j<=ny ;j++) slack[j]=inf;
    52         while (1)
    53         {
    54             memset(visx,0,sizeof(visx));
    55             memset(visy,0,sizeof(visy));
    56             if (dfs(x)) break;
    57             int d=inf;
    58             for (int j=1 ;j<=ny ;j++)
    59             {
    60                 if (!visy[j] && slack[j]<d)
    61                     d=slack[j];
    62             }
    63             for (int i=1 ;i<=nx ;i++)
    64                 if (visx[i]) lx[i] -= d;
    65             for (int i=1 ;i<=ny ;i++)
    66             {
    67                 if (visy[i]) ly[i] += d;
    68                 else slack[i] -= d;
    69             }
    70         }
    71     }
    72     int ans=0;
    73     for (int i=1 ;i<=ny ;i++)
    74         if (link[i]!=-1) ans += w[link[i] ][i];
    75     return ans;
    76 }
    77 
    78 int main()
    79 {
    80     while (scanf("%d",&n)!=EOF)
    81     {
    82         nx=ny=n;
    83         for (int i=1 ;i<=n ;i++)
    84         {
    85             for (int j=1 ;j<=n ;j++)
    86                 scanf("%d",&w[i][j]);
    87         }
    88         printf("%d
    ",KM());
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    Redis之分布式锁的使用
    Redis之lua脚本
    Redis 集群的水平扩缩容
    Redis集群搭建及原理
    Redis 的主从、哨兵架构
    CompletableFuture 使用介绍
    Spring Boot 2.x使用H2数据
    pom.xml
    nexus-staging-maven-plugin 踩坑
    安卓Hook折腾研究的笔记记录
  • 原文地址:https://www.cnblogs.com/huangxf/p/4337395.html
Copyright © 2011-2022 走看看