Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2134 | Accepted: 730 |
Description
Input
Output
Sample Input
6 4 1 2 3 4 2 3 1 4 4 2 3 1 3 1 2 4 1 3 4 2 1 4 2 3 2 1 3 2
Sample Output
2
Hint
Source
还是二分图的多重匹配
因为喜爱值在区间[1,b],所以可以枚举该差值,设最小喜爱值为low,最大喜爱值为high,初始时low=high=1,如果喜爱值在[low,high]的范围内可以将这n头牛以满足题意的方式安排好,那么就增大low值以用来减小差值,而如果没有安排方案,那么就增大high值来寻找新的安排方案.
#include<cstdio>
#include<string.h>
int mat[1010][25];
int c[25];
bool usedif[25];
int link[25][1010];
int n,b,low,high;
bool can(int t)
{
for(int i=1;i<=b;i++)
if(usedif[i]==0&&mat[t][i]<=high&&mat[t][i]>=low)
{
usedif[i]=true;
if(link[i][0]<c[i])
{
link[i][++link[i][0]]=t;
return true;
}
else
{
for(int j=1;j<=link[i][0];j++)
if(can(link[i][j]))
{
link[i][j]=t;
return true;
}
}
}
return false;
}
bool check()
{
for(int i=1;i<=b;i++) link[i][0]=0;
for(int i=1;i<=n;i++)
{
memset(usedif,0,sizeof(usedif));
if(!can(i)) return false;
}
return true;
}
int solve()
{
low=high=1;
int ans=1<<25-1;
while(low<=high&&high<=b)
{
if(check())
{
if(high-low+1<ans) ans=high-low+1;
low++;
}
else
high++;
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&b)!=EOF)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=b;j++)
{
int t;
scanf("%d",&t);
mat[i][t]=j;
}
for(int i=1;i<=b;i++) scanf("%d",&c[i]);
printf("%d/n",solve());
}
return 0;
}