有n头牛,m个牛棚,每头牛对牛棚的满意程度有一个排序,每个牛棚有牛数限制。
问如何分配各个牛,使得所有牛的满意程度的差值最小。
这题首先可以想到二分答案,对于每一种差值来求是否可行。
不想再搞网络流,学习了下二分图匈牙利解法。。
匹配时,对于每一种选择(牛棚),若满足范围,且有多余的容量,则匹配;
否则,对于该牛棚已经匹配过的牛进行增广。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define inf 0x3f3f3f3f
#pragma comment(linker, "/STACK:16777216")
#define eps 1e-6
#define ll __int64
const int maxn=1005;
using namespace std;
int link[25][maxn],rk[maxn][25],cap[maxn],num[maxn];
bool vis[maxn];
int n,m,r,l;
int path(int u)
{
int v;
for(v=0;v<m;v++)
{
if(rk[u][v]>=r&&rk[u][v]<=l&&!vis[v])
{
vis[v]=1;
if(num[v]<cap[v])
{
link[v][++num[v]]=u;// v牛棚的第num[v]头牛
return 1;
}
for(int i=1;i<=cap[v];i++)
{
if(path(link[v][i]))
{
link[v][i]=u;
return 1;
}
}
}
}
return 0;
}
int hungry()
{
memset(num,0,sizeof num);
memset(link,-1,sizeof link);
for(int i=0;i<n;i++)
{
memset(vis,0,sizeof vis);
if(!path(i)) return 0;
}
return 1;
}
int main()
{
int mid,ans,i,j;
while(~scanf("%d%d",&n,&m))
{
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
scanf("%d",&ans);
rk[i][--ans]=j;//存ans这个牛棚对于i这头牛的排序是多少
}
for(i=0;i<m;i++)
scanf("%d",&cap[i]);
r=l=0;
ans=inf;
while(r<=l&&l<m)
{
mid=l-r+1;
if(hungry())
{
r++;
if(mid<ans)
ans=mid;
}
else l++;
}
printf("%d\n",ans);
}
return 0;
}