KM简单题,但是要注意一些东西。
1. 题目说的500*500个点的图, 按照KM的复杂度是不能过的, 但是因为这题数据不行, 所以这样也是无压力的可以过, 但是为了保险,还是用邻接表比较好
2. 题目中有一个关键的话 “he still wants to design a creative plan such that no student is assigned to a room he/she dislikes” , 意思就是不能将学生分配到他评价为负的房间,这样就代表了读数据时负边无效。
3.因为没有给出n,m的大小, 所以按照一般的KM算法可能会出现死循环, 这时要加一个判断条件, 当在进行一次匈牙利找增广路未成功时, 如果发现最小的(ui+uj-wij)(x在路径中,而y不在路径中的所有边的最小值)为INF时,就说明算法在往后进行都无法找到增广路,直接返回-1
Interesting Housing Problem
Time Limit: 10000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2057 Accepted Submission(s): 768
Problem 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?
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
ifor 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.
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
Source
Recommend
lcy
#include <stdio.h> #include <algorithm> #include <string.h> #include <iostream> using namespace std; #define N 501 #define INF 0x3fffffff struct node { int to,next; int w; }edge[50001]; int cnt,pre[N]; int n,m,e; int frt[N]; int wx[N],wy[N]; int save[N]; int markx[N],marky[N]; void add_edge(int u,int v,int w) { edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=pre[u]; pre[u] = cnt++; } int dfs(int s) { markx[s]=1; for(int p=pre[s];p!=-1;p=edge[p].next) { int v=edge[p].to; if( wx[s]+wy[v]-edge[p].w < save[v]) save[v]=wx[s]+wy[v]-edge[p].w; if(marky[v]==1||wx[s]+wy[v]!=edge[p].w) continue; marky[v]=1; if(frt[v]==-1 || dfs(frt[v])==1) { frt[v]=s; return 1; } } return 0; } int KM() { memset(frt,-1,sizeof(frt)); memset(wx,0,sizeof(wx)); memset(wy,0,sizeof(wy)); for(int i=1;i<=n;i++) for(int p=pre[i];p!=-1;p=edge[p].next) wx[i]=max(wx[i],edge[p].w); for(int i=1;i<=n;i++) { while(1) { memset(markx,0,sizeof(markx)); memset(marky,0,sizeof(marky)); for(int j=1;j<=m;j++) save[j]=INF; if( dfs(i) == 1 ) break; int mi=INF; for(int j=1;j<=m;j++) if(marky[j]==0 && save[j]<mi) mi = save[j]; if(mi==INF) return -1; for(int j=1;j<=n;j++) if(markx[j]==1) wx[j]-=mi; for(int j=1;j<=m;j++) if(marky[j]==1) wy[j]+=mi; } } int sum=0; for(int i=1;i<=n;i++) for(int p=pre[i];p!=-1;p=edge[p].next) if(frt[edge[p].to]==i) sum+=edge[p].w; return sum; } int main() { int tt=1; while(scanf("%d%d%d",&n,&m,&e)!=EOF) { cnt=0; memset(pre,-1,sizeof(pre)); for(int i=0;i<e;i++) { int x,y; int key; scanf("%d%d%d",&x,&y,&key); x++; y++; if(key>=0) { add_edge(x,y,key); } } printf("Case %d: ",tt++); if(n>m) printf("-1\n"); else printf("%d\n",KM()); } return 0; }