链接:点击打开链接
题意: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;
}