链接:点击打开链接
题意:N个人,M个宿舍,接下来E行代表S号学生对R号宿舍的评分为V(每个学生只有评分为正或是0才会住,评分为负数的则不会去住),如果学生没有注满则输出-1,问学生都住进去后最大评分总和是多少
代码:
#include <iostream> #include <stdio.h> #include <string.h> #include <climits> #include <algorithm> #define INF 1e9 using namespace std; int s[605][605],visx[605],visy[605],match[605]; int lx[605],ly[605]; int n,m,e,sum,ans; int hungarian(int x){ int i; visx[x]=1; for(i=1;i<=m;i++){ if(!visy[i]&&lx[x]+ly[i]==s[x][i]){ visy[i]=1; if(!match[i]||hungarian(match[i])){ match[i]=x; return 1; } } } return 0; } int KM(){ int i,j,k,temp; memset(lx,0,sizeof(lx)); memset(ly,0,sizeof(ly)); memset(match,0,sizeof(match)); for(i=1;i<=n;i++) for(j=1;j<=m;j++) lx[i]=max(lx[i],s[i][j]); for(i=1;i<=n;i++){ while(1){ memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(hungarian(i)) break; else{ temp=INT_MAX; for(j=1;j<=n;j++) if(visx[j]){ for(k=1;k<=m;k++) if(!visy[k]) temp=min(temp,lx[j]+ly[k]-s[j][k]); } if(temp==INT_MAX) return -1; //如果没有增广路就证明没有匹配的,直接return,否则会TLE for(j=1;j<=n;j++) if(visx[j]) lx[j]-=temp; for(j=1;j<=m;j++) if(visy[j]) ly[j]+=temp; } } } for(i=1;i<=m;i++) if(match[i]!=0){ //如果有一个学生不匹配就return -1 if(s[match[i]][i]!=-INF) sum+=s[match[i]][i]; else return -1; } return sum; } //KM算法模板 int main(){ int i,j,a,b,c,cur; cur=1; while(scanf("%d%d%d",&n,&m,&e)!=EOF){ for(i=1;i<=n;i++) for(j=1;j<=m;j++) s[i][j]=-INF; //这个赋成INT_MIN就WA...... while(e--){ scanf("%d%d%d",&a,&b,&c); if(c>=0) //只有c>=0时才赋给s s[a+1][b+1]=c; } sum=0; printf("Case %d: %d\n",cur++,KM()); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-28 19:06:00