#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define REP(i,a,b) for(register int i = (a), i##_end_ = (b); i <= i##_end_ ; ++i)
const int maxn = 310;
const int oo = 0x3f3f3f3f;
int n,m,ans,lack,v[maxn][maxn],lx[maxn],ly[maxn],par[maxn],slack[maxn];
bool vx[maxn],vy[maxn];
bool dfs(int x)
{
vx[x] = 1;
REP(i,1,n)
{
if(vy[i])continue;
int t = lx[x] + ly[i] - v[x][i];
if(!t)
{
vy[i] = 1;
if(par[i] == -1 || dfs(par[i]))
{
par[i] = x;
return 1;
}
}
else slack[i] = min(slack[i], t);
}
return 0;
}
void km()
{
memset(par,-1,sizeof(par));
REP(i,1,n)
{
REP(j,1,n) slack[j] = oo;
while(1)
{
memset(vx,0,sizeof(vx));
memset(vy,0,sizeof(vy));
if(dfs(i))break;
int dx = oo;
REP(j, 1, n)
if(!vy[j] && slack[j] < dx)
dx = slack[j];
REP(j, 1, n)
if(vx[j])
lx[j] -= dx;
REP(j, 1, n)
if(vy[j])
ly[j] += dx;
else slack[j] -= dx;
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
ans = 0;
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
memset(slack, 0x3f, sizeof slack);
REP(i, 1, n)
REP(j,1, n)
{
scanf("%d",&v[i][j]);
lx[i] = max(v[i][j], lx[i]);
}
km();
REP(i,1,n)ans += v[par[i]][i];
printf("%d\n",ans);
}
return 0;
}
转载于:https://www.cnblogs.com/brodrinkwater/p/7527988.html