考虑二分答案
把男女生都拆点,拆成喜欢和不喜欢\(S\)向男生喜欢连边,容量\(mid\),男生喜欢向不喜欢连边,容量\(k\),女生同理 然后男生喜欢向女生喜欢连边,男生不喜欢向女生不喜欢连边 然后跑一遍最大流看是否满流即可//minamoto#include#define inf 0x3f3f3f3f#define R register#define fp(i,a,b) for(R int i=a,I=b+1;i I;--i)#define go(u) for(R int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)#define gg(u) for(R int &i=cur[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)using namespace std;const int N=1005,M=100005;struct eg{int v,nx,w;}e[M];int head[N],tot=1;inline void add(R int u,R int v,R int w){ e[++tot]={v,head[u],w},head[u]=tot; e[++tot]={u,head[v],0},head[v]=tot;}int n,dep[N],cur[N],S,T,q[N],hh[N],res,k,h,t,l,r,mid,ans;char s[N];bool bfs(){ fp(i,S,T)cur[i]=head[i],dep[i]=-1; q[h=t=1]=S,dep[S]=0; while(h<=t){ int u=q[h++]; go(u)if(e[i].w&&dep[v]<0){ dep[v]=dep[u]+1,q[++t]=v; if(v==T)return true; } }return false;}int dfs(int u,int lim){ if(u==T||!lim)return lim; int flow=0,f; gg(u)if(dep[v]==dep[u]+1&&(f=dfs(v,min(lim,e[i].w)))){ flow+=f,lim-=f; e[i].w-=f,e[i^1].w+=f; if(!lim)break; }return flow;}int dinic(){int flow=0;while(bfs())flow+=dfs(S,inf);return flow;}bool check(){ fp(i,S,T)head[i]=hh[i];tot=res;for(R int i=2;i<=tot;i+=2)e[i].w+=e[i^1].w,e[i^1].w=0; fp(i,1,n)add(S,i,mid);fp(i,1,n)add(i+2*n,T,mid); return dinic()==mid*n;}int main(){// freopen("testdata.in","r",stdin); scanf("%d%d",&n,&k),S=0,T=4*n+1; fp(i,1,n){ scanf("%s",s+1); fp(j,1,n)s[j]=='Y'?add(i,j+2*n,1):add(i+n,j+3*n,1); }if(k){ fp(i,1,n)add(i,i+n,k);fp(i,1,n)add(i+3*n,i+2*n,k); }fp(i,S,T)hh[i]=head[i];res=tot; l=0,r=n; while(l<=r){ mid=(l+r)>>1; check()?(ans=mid,l=mid+1):(r=mid-1); }printf("%d\n",ans);return 0;}