题目描述
传送门
题解
KM算法
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 320
#define inf 1000000000
using namespace std;
int n,m,pdx[N],pdy[N],cx[N],cy[N],belong[N],slack[N],val[N][N];
bool dfs(int x)
{
pdx[x]=1;
for (int i=1;i<=m;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(gap,slack[i]);
}
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<=m;j++) cx[i]=max(cx[i],val[i][j]);
}
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;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<=m;j++)
if (!pdy[j]) d=min(d,slack[j]);
for (int j=1;j<=n;j++)
if (pdx[j]) cx[j]-=d;
for (int j=1;j<=m;j++)
if (pdy[j]) cy[j]+=d;
else slack[j]-=d;
}
}
int ans=0;
for (int i=1;i<=m;i++) ans+=val[belong[i]][i];
return ans;
}
int main()
{
freopen("a.in","r",stdin);
while (scanf("%d%d",&n,&m)!=EOF) {
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&val[i][j]),val[i][j]*=10000;
int sum=0;
for (int i=1;i<=n;i++) {
int x; scanf("%d",&x);
sum+=val[i][x]; val[i][x]++;
}
sum/=10000;
int ans=km();
printf("%d %d\n",n-ans%10000,ans/10000-sum);
}
}