1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define M 1000 5 #define inf 0x7fffffff 6 using namespace std; 7 int T,n,k,sum,cnt=1,head[M],next[10*M],u[10*M],v[10*M],d[2*M],q[2*M],mp[M][M]; 8 char ch[66]; 9 void jia(int a1,int a2,int a3) 10 { 11 cnt++; 12 u[cnt]=a2; 13 v[cnt]=a3; 14 next[cnt]=head[a1]; 15 head[a1]=cnt; 16 return; 17 } 18 bool bfs() 19 { 20 memset(d,0,sizeof(int)*(T+2)); 21 int h=0,t=1; 22 q[1]=0; 23 d[0]=1; 24 for(;h<t;) 25 { 26 h++; 27 int p=q[h]; 28 for(int i=head[p];i;i=next[i]) 29 if(!d[u[i]]&&v[i]) 30 { 31 d[u[i]]=d[p]+1; 32 if(d[T]) 33 return 1; 34 t++; 35 q[t]=u[i]; 36 } 37 } 38 return 0; 39 } 40 int dinic(int s,int f) 41 { 42 if(s==T) 43 return f; 44 int rest=f; 45 for(int i=head[s];i&&rest;i=next[i]) 46 if(v[i]&&d[u[i]]==d[s]+1) 47 { 48 int now=dinic(u[i],min(rest,v[i])); 49 if(!now) 50 d[u[i]]=0; 51 v[i]-=now; 52 v[i^1]+=now; 53 rest-=now; 54 } 55 return f-rest; 56 } 57 bool pan(int a1) 58 { 59 memset(head,0,sizeof(head)); 60 cnt=1; 61 for(int i=1;i<=n;i++) 62 { 63 jia(0,i,a1); 64 jia(i,0,0); 65 jia(i,n+i,k); 66 jia(n+i,i,0); 67 jia(3*n+i,T,a1); 68 jia(T,3*n+i,0); 69 jia(2*n+i,3*n+i,k); 70 jia(3*n+i,2*n+i,0); 71 } 72 for(int i=1;i<=n;i++) 73 for(int j=1;j<=n;j++) 74 if(mp[i][j]) 75 { 76 jia(i,3*n+j,1); 77 jia(3*n+j,i,0); 78 } 79 else 80 { 81 jia(n+i,2*n+j,1); 82 jia(2*n+j,n+i,0); 83 } 84 sum=0; 85 for(;bfs();) 86 sum+=dinic(0,inf); 87 if(sum<a1*n) 88 return 0; 89 return 1; 90 } 91 int main() 92 { 93 scanf("%d%d",&n,&k); 94 T=(4*n)+1; 95 for(int i=1;i<=n;i++) 96 { 97 scanf("%s",ch+1); 98 for(int j=1;j<=n;j++) 99 if(ch[j]=='Y') 100 mp[i][j]=1; 101 } 102 int l=0,r=50,ans=0; 103 for(;l<=r;) 104 { 105 int mid=(l+r)>>1; 106 if(pan(mid)) 107 { 108 l=mid+1; 109 ans=l; 110 } 111 else 112 r=mid-1; 113 } 114 printf("%d\n",ans-1); 115 return 0; 116 }
网络流 将男女进行拆点,二分答案,同一个人之间建容量k的边,源汇分别向男女连mid的边,再根据喜欢不喜欢对男女进行连边,使如果不喜欢的话要走同一个人之间的那一条边,最后
观察一下是否满流。