做法就是KM算法
我的建图过程如下:
把食品供应点拆开,不要让他成为一个点,如果一个食品供应点能够供应2个人,那就把它拆开成两个点,由于食品供应点的所有人数之和是等于员工数的,所以刚好构成一个两边点数一样的一个二分图,然后从员工到供应点连边的边权就是喜好度,然后再用KM算法进行最大带权匹配就好了,最后建的图是一个M*M的矩阵,由于M小于300,所以KM算法能够过。
也见到过别人用DP过掉的,不过没有想通。。DP一直很弱。。
话说我已经退役了,这个博客很少用了。。
#include
#include
#include
#define inf 99999999
#define maxn 305
using namespace std;
int n,m;
int a[maxn];
int map[maxn][maxn];
int temp[maxn][maxn];
int link[maxn];
int lx[maxn],ly[maxn];
bool x[maxn],y[maxn];
bool dfs(int u)
{
int i;
x[u]=true;
for(i=1;i<=n;i++)
{
if(lx[u]+ly[i]==map[u][i]&&!y[i])
{
y[i]=true;
if(link[i]==-1||dfs(link[i]))
{
link[i]=u;
return true;
}
}
}
return false;
}
int main()
{
int i,j,k,num;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(i=1;i<=m;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&temp[i][j]);
for(i=1;i<=n;i++)
{
num=0;
for(j=1;j<=m;j++)
{
for(k=1;k<=a[j];k++)
{
num++;
map[i][num]=temp[i][j];
}
}
}
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
memset(link,-1,sizeof(link));
memset(ly,0,sizeof(ly));
for(i=0;i
lx[i]=inf;
for(k=1;k<=n;k++)
{
while(1)
{
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
if(dfs(k))
break;
int d=inf;
for(i=1;i<=n;i++)
if(x[i])
for(j=1;j<=n;j++)
if(!y[j]&&lx[i]+ly[j]-map[i][j]
d=lx[i]+ly[j]-map[i][j];
for(i=1;i<=n;i++)
if(x[i])
lx[i]=lx[i]-d;
for(i=1;i<=n;i++)
if(y[i])
ly[i]=ly[i]+d;
}
}
int ans1=0,ans2=0;
for(i=1;i<=n;i++)
ans1=ans1+map[link[i]][i];
printf("%d\n",ans1);
}
return 0;
}