被这题坑了多次,就一 二分+二分图多重匹配。
View Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=1500,M=50000; 6 int head[N],nc; 7 struct edge 8 { 9 int x,y,next; 10 } edge[M]; 11 void add(int x,int y) 12 { 13 edge[nc].x=x; 14 edge[nc].y=y; 15 edge[nc].next=head[x]; 16 head[x]=nc++; 17 } 18 int cow[N][25],bar[25]; 19 int lk[25][N],slk[25],co,ba; 20 bool chk[25]; 21 bool findpath(int x) 22 { 23 for(int i=head[x];i!=-1;i=edge[i].next) 24 { 25 int t=edge[i].y; 26 if(!chk[t]) 27 { 28 chk[t]=true; 29 if(slk[t]<bar[t]) 30 { 31 lk[t][slk[t]++]=x; 32 return true; 33 } 34 for(int j=0;j<slk[t];j++) 35 { 36 if(findpath(lk[t][j])) 37 { 38 lk[t][j]=x; 39 return true; 40 } 41 } 42 } 43 } 44 return false; 45 } 46 bool maxmatch() 47 { 48 for(int i=1;i<=co;i++) 49 { 50 memset(chk,false,sizeof(chk)); 51 if(!findpath(i)) 52 return false; 53 } 54 return true; 55 } 56 bool solve(int mid) 57 { 58 for(int i=1;i+mid<=ba+1;i++) 59 { 60 memset(head,-1,sizeof(head)); 61 nc=0; 62 for(int j=1;j<=co;j++) 63 for(int k=0;k<mid;k++) 64 add(j,cow[j][i+k]); 65 memset(slk,0,sizeof(slk)); 66 if(maxmatch()) 67 return true; 68 } 69 return false; 70 } 71 int main() 72 { 73 while(scanf("%d%d",&co,&ba)!=EOF) 74 { 75 for(int i=1; i<=co; i++) 76 for(int j=1;j<=ba;j++) 77 scanf("%d",&cow[i][j]); 78 for(int i=1;i<=ba;i++) 79 { 80 scanf("%d",&bar[i]); 81 if(bar[i]>co) 82 bar[i]=co; 83 } 84 int ll=1,rr=ba,mid,ans=ba; 85 while(ll<=rr) 86 { 87 mid=(ll+rr)>>1; 88 if(solve(mid)) 89 { 90 ans=mid; 91 rr=mid-1; 92 } 93 else 94 { 95 ll=mid+1; 96 } 97 } 98 printf("%d\n",ans); 99 } 100 return 0; 101 }