题目大意:
给定每一个人能支付的房子价值,每个人最多且必须拥有一套房子,问最后分配房子可得到的最大收益
抄了个别人的KM模板,就这样了。。。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 305
const int INF = 0x7fffffff;
int n , nx , ny;
int slack[N] , lx[N] , ly[N] , linker[N] , w[N][N] , visx[N] , visy[N]; int dfs(int u)
{
visx[u] = ;
for(int y= ; y<=ny ; y++){
if(visy[y]) continue;
int tmp = lx[u]+ly[y]-w[u][y];
if(tmp == ){
visy[y]=;
if(linker[y]==- || dfs(linker[y])){
linker[y]=u;
return ;
}
}
else if(slack[y]>tmp) slack[y] = tmp;
}
return ;
} int KM()
{
memset(linker , - , sizeof(linker));
memset(ly , , sizeof(ly));
//lx初始化为最大的边长
for(int i= ; i<=nx ; i++)
{
lx[i] = -INF;
for(int j= ; j<=ny ; j++)
lx[i] = max(lx[i] , w[i][j]);
}
for(int i= ; i<=nx ; i++){
for(int j= ; j<=ny ; j++){
slack[j] = INF;
}
while(true){
memset(visx , , sizeof(visx));
memset(visy , , sizeof(visy));
if(dfs(i)) break; //若找不到增广路,就需要改变一下标号
int a = INF;
for(int k= ; k<=ny ; k++)
if(!visy[k]&&a>slack[k])
a = slack[k];
for(int k= ; k<=nx ; k++)
if(visx[k])
lx[k]-=a;
for(int k= ; k<=nx ; k++)
if(visy[k]) ly[k]+=a;
else slack[k]-=a;
}
}
int res = ;
for(int i= ; i<=ny ; i++)
if(linker[i]!=-)
res+=w[linker[i]][i];
return res;
} int main()
{
// freopen("in.txt" , "r" , stdin);
while(~scanf("%d" , &n))
{
for(int i= ; i<=n ; i++)
for(int j= ; j<=n ; j++) scanf("%d" , &w[i][j]);
nx = n , ny = n;
int ans = KM();
printf("%d\n" , ans);
}
return ;
}