传送门
拆点网络流+二分答案。
将每一个人拆成ix和iy
如果男女互相喜欢,则在x节点之间加边。
否则在y节点之间加边。(边权为1)
然后男生从x连向y,女生从y连向x,连流量为k的边。
从原点向男生的x节点连流量为a的边。
从女生的x节点向汇点连流量为a的边。
然后二分答案a,判断是否满足n*a==maxflow即可。
#include<cstring>
#include<cmath>
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#define inf 2100000000
using namespace std;
struct edge{
int from,to,next,u;
}e[10005];
char a[55][55];
int head[205],q[10005],dis[205],from[205];
int n,k,l,r,m,S,T,s,ans,tot;
inline int add(int x,int y,int u){
tot++;
e[tot].from=x;
e[tot].to=y;
e[tot].u=u;
e[tot].next=head[x];
head[x]=tot;
}
inline int ins(int x,int y,int u){
add(x,y,u);
add(y,x,0);
}
inline void build(int x){
tot=1;
memset(head,0,sizeof(head));
for (int i=1;i<=n;i++) ins(S,i,x);
for (int i=1;i<=n;i++) ins(i+2*n,T,x);
for (int i=1;i<=n;i++) ins(i,i+n,k);
for (int i=1;i<=n;i++) ins(i+3*n,i+2*n,k);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][j]=='Y') ins(i,j+2*n,1);
else ins(i+n,j+3*n,1);
}
inline int spfa(){
for (int i=1;i<=4*n+2;i++) dis[i]=inf;
dis[4*n+1]=0;
int h=0,t=1,x;
q[1]=4*n+1;
while (h<t){
h++;
x=q[h];
for (int i=head[x];i;i=e[i].next)
if (dis[e[i].to]==inf&&e[i].u!=0){
dis[e[i].to]=dis[x]+1;
from[e[i].to]=i;
q[++t]=e[i].to;
}
}
if (dis[4*n+2]!=inf) return 1;
return 0;
}
inline void del(){
int x=inf;
s++;
for (int i=T;i!=S;i=e[from[i]].from){
e[from[i]].u--;
e[from[i]^1].u++;
}
}
int main(){
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++) scanf("%s",a[i]+1);
l=0; r=50; S=n*4+1; T=S+1;
while (l<=r){
m=(l+r)/2;
build(m);
s=0;
while (spfa()) del();
if (s==m*n){ans=m; l=m+1;}
else r=m-1;
}
printf("%d",ans);
}