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\n",++ncase,KM()); 67 } 68 }
2018-11-18
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。