HDU2426-Interesting Housing Problem KM 稍微复杂一点

来源:互联网 发布:northwind数据库下载 编辑:程序博客网 时间:2024/04/30 08:22

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 5
0 1 5
0 2 7
1 1 6
1 2 3
2 4 5

1 1 1
0 0 0

1 1 0

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

题意:学生配宿舍,n个学生对m个宿舍有一个满意度评价,学生只会入住其正面满意度评价的宿舍,求最大的满意度,学生不能全部入住输出-1。

思路:线性思考,x集合为学生,y集合为宿舍,建个图就好了,拒绝负权边。
题目数据比较水。
代码遇到n>m的时候会死循环。
原题目discuss里面提出了局限性,就是对于每一个X点集中的点,他都必须找到一个与之匹配 的Y点集中的点才能退出while循环,如果找不到,就会死循环。而n>m必然死循环……很容易理解。
解决方案是预先匈牙利处理看能不能完备匹配,或者预先处理掉n>m的情况。不过这道题应该默认就给了完备匹配了,貌似没有你n>m的情况。

#include<bits/stdc++.h>using namespace std;#define M 1010#define inf 0x3f3f3f3fint n,nx,ny,m,e;int link[M],lx[M],ly[M],slack[M];    int visx[M],visy[M],w[M][M];int DFS(int x){    visx[x] = 1;    for (int y = 0;y < ny;y ++)    {        if (visy[y])            continue;        int t = lx[x] + ly[y] - w[x][y];        if (t == 0)              {            visy[y] = 1;            if (link[y] == -1||DFS(link[y]))            {                link[y] = x;                return 1;            }        }        else if (slack[y] > t)              slack[y] = t;    }    return 0;}int KM(){    int i,j;    memset (link,-1,sizeof(link));    memset (ly,0,sizeof(ly));    for (i = 0;i < nx;i ++)                    for (j = 0,lx[i] = -inf;j < ny;j ++)            if (w[i][j] > lx[i])                lx[i] = w[i][j];    for (int x = 0;x < nx;x ++)    {        for (i = 0;i < ny;i ++)            slack[i] = inf;        while (1)        {            memset (visx,0,sizeof(visx));            memset (visy,0,sizeof(visy));            if (DFS(x))                     break;              int d = inf;            for (i = 0;i < ny;i ++)                if (!visy[i]&&d > slack[i])                    d = slack[i];            for (i = 0;i < nx;i ++)                if (visx[i])                    lx[i] -= d;            for (i = 0;i < ny;i ++)                  if (visy[i])                    ly[i] += d;                else                    slack[i] -= d;        }    }    int cnt = 0;     int res = 0;    for (i = 0;i < ny;i ++)        if (link[i] > -1 && w[link[i]][i] != -inf)            res += w[link[i]][i],cnt++;    if(cnt == n)            return res;    else    return -1;}int main(){    int casee = 1;    freopen("h2426.in","r",stdin);    while(~scanf("%d%d%d",&n,&m,&e))    {        nx = n;        ny = m;        for(int i = 0;i <= M;i++)        {            for(int j = 0;j <= M;j++)            {                w[i][j] = -inf;            }        }        for(int i = 0;i < e;i++)        {            int u,v,w1;            scanf("%d%d%d",&u,&v,&w1);            if(w1 >= 0) w[u][v] = w1;        }            int res = KM();            printf("Case %d: %d\n",casee++,res);    }    return 0;}
0 0
原创粉丝点击