#include<iostream>
using namespace std;
const int maxn=300+5;
const int inf=(1<<30);
int w[maxn][maxn];
int lx[maxn],ly[maxn];
int s[maxn],t[maxn];
int slack[maxn];
int match[maxn];
int n;
bool find(int i)
{
s[i]=true;
for(int j=1;j<=n;j++)
{
if(t[j]) continue;
int tmp=lx[i]+ly[j]-w[i][j];
if(tmp==0)
{
t[j]=true;
if(match[j]==-1||find(match[j]))
{
match[j]=i;
return true;
}
}
else if(slack[j]>tmp) slack[j]=tmp;
}
return false;
}
void update()
{
int d=inf;
for(int i=1;i<=n;i++)
if(!t[i]&&d>slack[i]) d=slack[i];
for(int i=1;i<=n;i++)
if(s[i]) lx[i]-=d;
for(int i=1;i<=n;i++){
if(t[i]) ly[i]+=d;
else slack[i]-=d;
}
}
void KM()
{
memset(match,-1,sizeof(match));
memset(ly,0,sizeof(ly));
for(int i=1;i<=n;i++)
{
lx[i]=-inf;
for(int j=1;j<=n;j++)
if(w[i][j]>lx[i]) lx[i]=w[i][j];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++) slack[j]=inf;
for(;;)
{
memset(s,0,sizeof(s));
memset(t,0,sizeof(t));
if(find(i)) break;else update();
}
}
}
int main()
{
while(~scanf("%d",&n))
{
memset(w,0,sizeof(w));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) scanf("%d",&w[i][j]);
KM();
int ans=0;
for(int i=1;i<=n;i++) if(match[i]!=-1) ans+=w[match[i]][i];
printf("%d\n",ans);
}
return 0;
}
KM算法O(n^3)模板 hdu2255
最新推荐文章于 2020-10-09 17:39:44 发布