zoukankan      html  css  js  c++  java
  • HDU 2426 Interesting Housing Problem (最大权完美匹配)【KM】

    <题目链接>

    题目大意:

    学校里有n个学生和m个公寓房间,每个学生对一些房间有一些打分,如果分数为正,说明学生喜欢这个房间,若为0,对这个房间保持中立,若为负,则不喜欢这个房间。学生不会住进不喜欢的房间和没有打分的房间。问安排这n个学生来求最大的分数,如果不能够使这些学生全部入住房间,就输出-1,每个房间最多只能住一个学生。

    解题分析:

    因为需要求带权二分图,所以用KM算法,需要注意的是,边权为负的两点不能进行匹配,并且,最后需要判断是否符合题意,即是否所有学生都有房间。

     1 #include <cstring>
     2 #include <cstdio>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int N = 505;
     7 #define INF 0x3f3f3f3f
     8 #define CLR(a,b) memset(a,b,sizeof(a))
     9 #define rep(i,s,t) for(int i=s;i<t;i++)
    10 
    11 int nx,ny,k;
    12 int w[N][N],linker[N],visx[N],visy[N],lx[N],ly[N],slack[N];
    13 bool DFS(int x){
    14     visx[x]=1;
    15     rep(y,0,ny){
    16         if(!visy[y]&&w[x][y]>=0){    //如果w[x][y]<0,就不能匹配
    17             int tmp=lx[x]+ly[y]-w[x][y];
    18             if(tmp==0){
    19                 visy[y]=1;
    20                 if(linker[y]==-1||DFS(linker[y])){
    21                     linker[y]=x;
    22                     return true;
    23                 }
    24             }else slack[y]=min(slack[y],tmp);
    25         }
    26     }
    27     return false;
    28 }
    29 int KM(){    
    30     CLR(linker,-1);CLR(ly,0);
    31     rep(i,0,nx){
    32         lx[i]=-INF;
    33         rep(j,0,ny){
    34             lx[i]=max(lx[i],w[i][j]);
    35         }
    36         if(lx[i]<0)return -1;    //在取完最值后,lx[i]仍然<0,说明该人不想住进任何一间房子,所以直接返回-1即可
    37     }
    38     rep(x,0,nx){
    39         rep(i,0,ny)slack[i]=INF;
    40         while(true){
    41             CLR(visx,0);CLR(visy,0);
    42             if(DFS(x))break;
    43             int d=INF;
    44             rep(i,0,ny)if(!visy[i])d=min(d,slack[i]);
    45             rep(i,0,nx)if(visx[i])lx[i]-=d;
    46             rep(i,0,ny)
    47                 if(visy[i])ly[i]+=d;
    48                 else slack[i]-=d;
    49         }
    50     }
    51     int res=0,count=0;
    52     rep(y,0,ny){
    53         if(linker[y]!=-1)res+=w[linker[y]][y],count++;    //count记录有房子住的人数 
    54     }
    55     if(count<nx)return -1;
    56     return res;
    57 }
    58 int main(){
    59     int ncase=0;
    60     while(~scanf("%d%d%d",&nx,&ny,&k)){
    61         CLR(w,-1);
    62         rep(i,0,k){
    63             int a,b,c;scanf("%d%d%d",&a,&b,&c);
    64             w[a][b]=c;
    65         }
    66         printf("Case %d: %d
    ",++ncase,KM());
    67     }
    68 }

    2018-11-18

  • 相关阅读:
    【BZOJ 3709: [PA2014]Bohater】
    清北学堂2019.8.10 & 清北学堂2019.8.11 & 清北学堂2019.8.12
    清北学堂2019.8.9
    清北学堂2019.8.8
    清北学堂2019.8.7
    清北学堂2019.8.6
    【洛谷T89379 【qbxt】复读警告】
    【洛谷T89353 【BIO】RGB三角形】
    【洛谷T89359 扫雷】
    【洛谷P2016战略游戏】
  • 原文地址:https://www.cnblogs.com/00isok/p/9979673.html
Copyright © 2011-2022 走看看