被这题坑了多次,就一 二分+二分图多重匹配。

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 }