没什么好说的,模板题
普通版
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
//typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100011122;
const double INFF=1e100;
const double eps=1e-8;
const int mod=9999991;
const int NN=305;
const int MM=2000010;
/* ****************** */
int w[NN][NN],lx[NN],ly[NN];
int match[NN],slack[NN];
bool visx[NN],visy[NN];
bool find(int x,int n)
{
visx[x]=true;
int i,t;
for(i=1;i<=n;i++)
{
if(visy[i])
continue;
t=lx[x]+ly[i]-w[x][i];
if(t==0)
{
visy[i]=true;
if(match[i]==-1 || find(match[i],n))
{
match[i]=x;
return true;
}
}
else
slack[i]=min(slack[i],t);
}
return false;
}
int KM(int n)
{
int i,j,t;
for(i=1;i<=n;i++)
{
match[i]=-1;
ly[i]=0;
lx[i]=-INF;
for(j=1;j<=n;j++)
lx[i]=max(lx[i],w[i][j]);
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
slack[j]=INF;
for(;;)
{
for(j=1;j<=n;j++)
visx[j]=visy[j]=false;
if( find(i,n) ) break;
t=INF;
for(j=1;j<=n;j++)
if(!visy[j])
t=min(t,slack[j]);
for(j=1;j<=n;j++)
{
if(visx[j])
lx[j]-=t;
if(visy[j])
ly[j]+=t;
}
}
}
t=0;
for(i=1;i<=n;i++)
{
t+=w[ match[i] ][i];
}
return t;
}
int main()
{
int i,j,n,ans;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&w[i][j]);
ans=KM(n);
printf("%d\n",ans);
}
return 0;
}
优化版
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
//typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100011122;
const double INFF=1e100;
const double eps=1e-8;
const int mod=9999991;
const int NN=305;
const int MM=2000010;
/* ****************** */
int w[NN][NN],lx[NN],ly[NN];
int prev_x[NN],prev_y[NN],son_y[NN],slack[NN],par[NN];
void adjust(int v)
{
son_y[v] = prev_y[v];
if(prev_x[ son_y[v] ]!=-2)
adjust( prev_x[ son_y[v] ] );
}
bool find(int v,int n)
{
int i,t;
for(i=1;i<=n;i++)
{
if(prev_y[i]==-1)
{
t=lx[v]+ly[i]-w[v][i];
if(slack[i]>t)
{
slack[i]=t;
par[i]=v;
}
if(t==0)
{
prev_y[i]=v;
if(son_y[i]==-1)
{
adjust(i);
return true;
}
if(prev_x[ son_y[i] ]!=-1)
continue;
prev_x[ son_y[i] ]=i;
if( find(son_y[i],n) )
return true;
}
}
}
return false;
}
int KM(int n)
{
int i,j,m;
bool flag;
for(i=1;i<=n;i++)
{
son_y[i]=-1;
ly[i]=0;
}
for(i=1;i<=n;i++)
{
lx[i]=-INF;
for(j=1;j<=n;j++)
lx[i]=max(lx[i],w[i][j]);
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
prev_x[j]=prev_y[j]=-1;
slack[j]=INF;
}
prev_x[i]=-2;
if(find(i,n))continue;
flag=false;
while(!flag)
{
m=INF;
for(j=1;j<=n;j++)
if(prev_y[j]==-1)
m=min(m,slack[j]);
for(j=1;j<=n;j++)
{
if(prev_x[j]!=-1)
lx[j]-=m;
if(prev_y[j]!=-1)
ly[j]+=m;
else
slack[j]-=m;
}
for(j=1;j<=n;j++)
if(prev_y[j]==-1 && !slack[j])
{
prev_y[j]=par[j];
if(son_y[j]==-1)
{
adjust(j);
flag=true;
break;
}
prev_x[ son_y[j] ]=j;
if( find( son_y[j],n ) )
{
flag=true;
break;
}
}
}
}
m=0;
for(i=1;i<=n;i++)
m+=w[ son_y[i] ][i];
return m;
}
int main()
{
int i,j,n,ans;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&w[i][j]);
ans=KM(n);
printf("%d\n",ans);
}
return 0;
}