HDU 2426 Interesting Housing Problem [N!=M的最佳二分匹配]

来源:互联网 发布:淘宝刷单被降权怎么办 编辑:程序博客网 时间:2024/05/29 19:19

题意:N个学生,M个房间,每个学生对部分房间进行评价,评价值有正有负,现安排房间,要求学生不能入住其不喜欢的房间,即只能入住评价值非负的房间,求一种方案使总评价值最大。

思路:最佳匹配模板KM,过程中求最佳,最后通过匹配情况判断能否满足N

#include<cstdio>#include<cstring>using namespace std;const int MAXN=505;const int INF=999999999;int map[MAXN][MAXN];int lx[MAXN],ly[MAXN];int mapch[MAXN];int stack[MAXN];bool sy[MAXN],sx[MAXN];int N,M,e;int find (int u){    int v,t;    sx[u]=1;    for(v=1;v<=M;v++){        if(sy[v]) continue;        t=lx[u]+ly[v]-map[u][v];        if(t==0){            sy[v]=1;            if(mapch[v]==-1||find(mapch[v])){                mapch[v]=u;                return 1;            }        }        else if(t<stack[v]) stack[v]=t;    }    return 0;}int KM(){    int i,j,k,d,cnt=0,sum=0;    for(i=1;i<=M;i++)        ly[i]=0;    memset(mapch,-1,sizeof(mapch));    for(i=1;i<=N;i++){        lx[i]=-INF;        for(j=1;j<=M;j++)            if(map[i][j]>lx[i])                lx[i]=map[i][j];    }    for(i=1;i<=N;i++){        for(j=1;j<=M;j++)            stack[j]=INF;        while(1){            for(k=1;k<=M;k++) sy[k]=0;            for(k=1;k<=N;k++) sx[k]=0;            if(find(i)) break;            d=INF;            for(k=1;k<=M;k++)                if(!sy[k]&&stack[k]<d)                    d=stack[k];            for(k=1;k<=N;k++)                if(sx[k]) lx[k]-=d;            for(k=1;k<=M;k++)                if(sy[k]) ly[k]+=d;                else stack[k]-=d;        }    }    for(i=1;i<=M;i++)        if(mapch[i]!=-1&&map[mapch[i]][i]!=INF){            sum+=map[mapch[i]][i];            cnt++;        }    if(cnt==N) return sum;//判断是否能完成n的最佳匹配    else return -1;}int main(){    int i,j;    int x,y,z;    int cas=0;    while(scanf("%d%d%d",&N,&M,&e)!=EOF){        for(i=1;i<=N;i++)            for(j=1;j<=M;j++)                map[i][j]=-INF;        while(e--){            scanf("%d%d%d",&x,&y,&z);            if(z>=0) //////////////map[x+1][y+1]=z;        }        printf("Case %d: ",++cas);        /*if(n>m){            printf("-1\n");            continue;        }*/        printf("%d\n",KM());    }    return 0;}/*测试:Sample Input3 5 50 1 50 2 71 1 61 2 32 4 51 1 10 0 01 1 0Sample OutputCase 1: 18Case 2: 0Case 3: -1*/


 

原创粉丝点击