HDU 2426 Interesting Housing Problem(二分图最优匹配)

来源:互联网 发布:火锅店软件 编辑:程序博客网 时间:2024/06/13 11:50

 题意:有N个学生和M个房间,每个学生可能会给多个房间打分.如果分数>=0,表示他可以选择这个房间.(如果分数<0,那么他不喜欢这个房间且他不能选这个房间). 且那些他没打过分的房间他也不能选.

           现在问你是否存在一个匹配使得每个学生分得一个单独的房间且每个房间最多1个学生.且这些房间都是学生打了分的且分数>0的房间? 如果存在输出分数和的最大值,如果不存在输出-1.

思路首先明显当输出N>M的时候直接输出-1.下面的情况就是N<=M时了.首先注意学生一定只能选那些他打了分的且分数>=0的房间.由于我们要求最优匹配用的KM算法,那么我们就应该用点集大小不对称的KM算法模板且由于最优匹配要求所有边都必须要有权值才行.那么我们对于那些原本不存在的边就赋值为负无穷.那么当我们求出最优匹配的时候,如果存在某条匹配边的权值是负无穷,那么代表本问题无解. 否则的话总权值就是最优匹配的权值解.


#include<cstdio>#include<cstring>#include<algorithm>#define INF 1e9using namespace std;const int maxn=500+10;struct Max_Match{    int n,m,W[maxn][maxn];    int Lx[maxn],Ly[maxn];    bool S[maxn],T[maxn];    int left[maxn];    bool match(int i)    {        S[i]=true;        for(int j=1;j<=m;j++)if(Lx[i]+Ly[j]==W[i][j] && !T[j])        {            T[j]=true;            if(left[j]==-1 || match(left[j]))            {                left[j]=i;                return true;            }        }        return false;    }    void update()    {        int a=1<<30;        for(int i=1;i<=n;i++)if(S[i])        for(int j=1;j<=m;j++)if(!T[j])            a = min(a, Lx[i]+Ly[j]-W[i][j]);        for(int i=1;i<=n;i++)if(S[i]) Lx[i]-=a;        for(int j=1;j<=m;j++)if(T[j]) Ly[j]+=a;    }    int solve(int n,int m)    {        this->n=n;        this->m=m;        memset(left,-1,sizeof(left));        memset(Lx,0,sizeof(Lx));        memset(Ly,0,sizeof(Ly));        for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            Lx[i]=max(Lx[i],W[i][j]);        for(int i=1;i<=n;i++)        {            while(true)            {                memset(S,0,sizeof(S));                memset(T,0,sizeof(T));                if(match(i)) break;                else update();            }        }        int ans=0;        for(int i=1;i<=m;i++)if(left[i]!=-1)        {            if(W[left[i]][i] != -INF)                ans += W[left[i]][i];            else return -1;        }        return ans;    }}KM;int main(){    int n,m,e,kase=0;    while(scanf("%d%d%d",&n,&m,&e)==3)    {        for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            KM.W[i][j]=-INF;        for(int i=0;i<e;i++)        {            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            ++u,++v;            if(w>=0) KM.W[u][v]=w;        }        printf("Case %d: %d\n",++kase,KM.solve(n,m));    }    return 0;}

Description

For any school, it is hard to find a feasible accommodation plan with every student assigned to a suitable apartment while keeping everyone happy, let alone an optimal one. Recently the president of University ABC, Peterson, is facing a similar problem. While Peterson does not like the idea of delegating the task directly to the class advisors as so many other schools are doing, he still wants to design a creative plan such that no student is assigned to a room he/she dislikes, and the overall quality of the plan should be maximized. Nevertheless, Peterson does not know how this task could be accomplished, so he asks you to solve this so-called "interesting" problem for him. 
Suppose that there are N students and M rooms. Each student is asked to rate some rooms (not necessarily all M rooms) by stating how he/she likes the room. The rating can be represented as an integer, positive value meaning that the student consider the room to be of good quality, zero indicating neutral, or negative implying that the student does not like living in the room. Note that you can never assign a student to a room which he/she has not rated, as the absence of rating indicates that the student cannot live in the room for other reasons. 
With limited information available, you've decided to simply find an assignment such that every student is assigned to a room he/she has rated, no two students are assigned to the same room, and the sum of rating is maximized while satisfying Peterson's requirement. The question is … what exactly is the answer? 
 

Input

There are multiple test cases in the input file. Each test case begins with three integers, N, M, and E (1 <= N <= 500, 0 <= M <= 500, 0 <= E <= min(N * M, 50000)), followed by E lines, each line containing three numbers, S i, R i, V i, (0 <= S i < N, 0 <= R i < M, |V i| <= 10000), describing the rating V i given by student S i for room R i. It is guaranteed that each student will rate each room at most once. 
Each case is followed by one blank line. Input ends with End-of-File. 
 

Output

For each test case, please output one integer, the requested value, on a single line, or -1 if no solution could be found. Use the format as indicated in the sample output. 
 

Sample Input

3 5 50 1 50 2 71 1 61 2 32 4 51 1 10 0 01 1 0
 

Sample Output

Case 1: 18Case 2: 0Case 3: -1
 


0 0