其实对萌新来说很不友好...
写了半天过不了...
现在我也不是很懂 只是会匈牙利
多练几篇再说吧。
不懂的可以移步链接:https://www.cnblogs.com/logosG/p/logos.html
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=505;
const int oo=1e9;
int lx[maxn], ly[maxn], vx[maxn], vy[maxn], match[maxn], slack[maxn];
int map[maxn][maxn];
int n, m;
bool find(int i)
{
vx[i]=1; ///相等子图中X集合
for(int j=1; j<=m; j++)
if(!vy[j])
{
int t=lx[i]+ly[j]-map[i][j];
if(t==0) ///当这条边在相等子图中
{
vy[j]=1; ///相等子图中Y集合
if(match[j]==-1||find(match[j]))
{
match[j]=i;
return true;
}
}
else slack[j]=min(slack[j],t);
}
return false;
}
int KM()
{
int ans=0;
memset(match,-1,sizeof(match));
memset(ly,0,sizeof(ly));
for(int i=1; i<=n; i++)
{
lx[i]=-oo;
for(int j=1; j<=m; j++)
lx[i]=max(lx[i],map[i][j]); ///顶标lx初始化保存的是连接i节点的最大边权值
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++) slack[j]=oo;
while(1)
{
memset(vx,0,sizeof(vx));
memset(vy,0,sizeof(vy));
if(find(i)) break;
int d=oo;
for(int j=1; j<=m; j++)
if(!vy[j]) d=min(d,slack[j]);
for(int j=1; j<=n; j++)
if(vx[j]) lx[j]-=d;
for(int j=1; j<=m; j++)
if(vy[j]) ly[j]+=d;
for(int j=1; j<=m; j++) slack[j]-=d;
}
}
for(int i=1; i<=m; i++)
if(match[i]!=-1) ans+=map[ match[i] ][i];
return ans;
}
int main()
{
while(cin >> n >> m)
{
for(int i=0; i<=n; i++)
for(int j=0; j<=m; j++) map[i][j]=-oo;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
int c;
scanf("%d",&c);
map[i][j]=max(map[i][j],100*c);
}
int sum=0;
for(int i=1,j; i<=n; i++)
{
scanf("%d",&j);
sum+=map[i][j]/100;
map[i][j]+=1;
}
int ans=KM();
printf("%d %d\n",n-ans%100,ans/100-sum);
}
return 0;
}