1. 程式人生 > >HDU 2426 Interesting Housing Problem (最大權完美匹配)【KM】

HDU 2426 Interesting Housing Problem (最大權完美匹配)【KM】

!= string += 需要 bsp std 題意 case 個學生

<題目鏈接>

題目大意:

學校裏有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

HDU 2426 Interesting Housing Problem (最大權完美匹配)【KM】