题目链接:https://vjudge.net/problem/POJ-3189
题目大意:
有(N)头牛,(B)个牛棚,每头牛对于不同牛棚的满意程度有大小之分,但每个牛棚的容量都是有限的。问如何安排可以使得所有牛对于自己的牛棚的最大满意程度和最小满意程度的差距最小,求出这个区间的长度。
知识点: 匹配、匈牙利算法
解题思路:
先二分长度,然后枚举起点,在确定好区间起点终点的前提下跑匈牙利算法(权值在区间外的边相当于不存在)。因为是多重匹配(即一个牛棚有可能匹配多头牛),所以需要改一下模板。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 int G[1010][25]; 7 int cap[25]; 8 int N,B; 9 bool used[25]; 10 int to[25][1000]; 11 12 bool finds(int x,int s,int e){ 13 for(int j=1;j<=B;j++){ 14 if(G[x][j]>=s&&G[x][j]<=e&&!used[j]){ 15 used[j]=true; 16 for(int k=0;k<cap[j];k++){ //遍历j牛棚的所有位置 17 if(to[j][k]==0||finds(to[j][k],s,e)){ //对于j牛棚的第k个位置的查询 18 to[j][k]=x; 19 return true; 20 } 21 } 22 } 23 } 24 return false; 25 } 26 bool can(int m){ 27 for(int s=1;s+m-1<=B;s++){ 28 memset(to,0,sizeof(to)); 29 int has=0; 30 for(int i=1;i<=N;i++){ 31 memset(used,false,sizeof(used)); 32 if(finds(i,s,s+m-1)) has++; 33 else break; 34 } 35 if(has==N) return true; 36 } 37 return false; 38 } 39 int main(){ 40 int val; 41 scanf("%d%d",&N,&B); 42 for(int i=1;i<=N;i++){ 43 for(int j=1;j<=B;j++){ 44 scanf("%d",&val); 45 G[i][val]=j; 46 } 47 } 48 for(int j=1;j<=B;j++) scanf("%d",&cap[j]); 49 int l=1,r=B; 50 int ans=1; 51 while(l<=r){ 52 int m=(l+r)>>1; 53 if(can(m)){ 54 ans=m; 55 r=m-1; 56 } 57 else 58 l=m+1; 59 } 60 printf("%d ",ans); 61 62 return 0; 63 }