题目描述
传送门
题解
KM算法的模板题。
这里链接一个不错的KM讲解
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 320
#define inf 1000000000
using namespace std;
int n,pdx[N],pdy[N],val[N][N],cx[N],cy[N],belong[N],vis[N],slack[N];
bool dfs(int x)
{
pdx[x]=1;
for (int i=1;i<=n;i++){
if (pdy[i]) continue;
int gap=cx[x]+cy[i]-val[x][i];
if (!gap) {
pdy[i]=1;
if (!belong[i]||dfs(belong[i])) {
belong[i]=x;
return true;
}
}
else slack[i]=min(slack[i],gap);
}
return false;
}
int km()
{
memset(belong,0,sizeof(belong));
memset(cy,0,sizeof(cy));
for (int i=1;i<=n;i++){
cx[i]=val[i][1];
for (int j=2;j<=n;j++) cx[i]=max(cx[i],val[i][j]);
}
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++) slack[j]=inf;
while (true) {
memset(pdx,0,sizeof(pdx));
memset(pdy,0,sizeof(pdy));
if (dfs(i)) break;
int d=inf;
for (int j=1;j<=n;j++)
if (pdy[j]==0) d=min(d,slack[j]);
for (int j=1;j<=n;j++) {
if (pdx[j]) cx[j]-=d;
if (pdy[j]) cy[j]+=d;
else slack[j]-=d;
}
}
}
int ans=0;
for (int i=1;i<=n;i++) ans+=val[belong[i]][i];
return ans;
}
int main()
{
freopen("a.in","r",stdin);
while (scanf("%d",&n)!=EOF) {
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++) scanf("%d",&val[i][j]);
printf("%d\n",km());
}
}