打了一遍KM算法的板子
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,l[305][305],match[305],ex1[305],ex2[305],slack[305];
char vis1[305],vis2[305];
inline int max(int a,int b)
{
return a>b?a:b;
}
inline int min(int a,int b)
{
return a<b?a:b;
}
bool dfs(int x)
{
vis2[x]=1;
for (int i=1;i<=n;++i)
{
if(vis1[i]) continue ;
int gap=ex1[i]+ex2[x]-l[i][x];
if(gap==0)
{
vis1[i]=1;
if(match[i]==0||dfs(match[i]))
{
return match[i]=x,1;
}
}
else
slack[i]=min(slack[i],gap);
}
return 0;
}
int KM(void)
{
memset(match,0,sizeof(match)),
memset(ex1,0,sizeof(ex1));
for (int i=1;i<=n;++i)
{
ex2[i]=l[1][i];
for (int j=2;j<=n;++j)
ex2[i]=max(ex2[i],l[j][i]);
}
for (int i=1;i<=n;++i)
{
fill(slack+1,slack+1+n,0x3f3f3f3f);
while(1)
{
memset(vis1,0,sizeof(vis1)),
memset(vis2,0,sizeof(vis2));
if(dfs(i)) break;
int d=0x3f3f3f3f;
for (int j=1;j<=n;++j)
if(!vis1[j])
d=min(d,slack[j]);
for (int j=1;j<=n;++j)
{
if(vis2[j])
ex2[j]-=d;
if(vis1[j])
ex1[j]+=d;
else
slack[j]-=d;
}
}
}
int res=0;
for (int i=1;i<=n;++i)
res+=l[i][match[i]];
return res;
}
int main(void)
{
register int i,j;
while(~scanf("%d",&n))
{
for (i=1;i<=n;++i)
for (j=1;j<=n;++j)
scanf("%d",&l[i][j]);
printf("%d\n",KM());
}
return 0;
}