首先考虑建图,因为
每个男孩最多只愿意和
个不喜欢的女孩跳舞,而每个女孩也最多只愿意和 个不喜欢的男孩跳舞。
所以对于每个男孩女孩均要建一个辅助点,到该点的权值为
接下来考虑源点到男孩与女孩到汇点的权值情况。
1.如果权值
2.权值大于答案,则有
所以,我可以用遍历权值从
坑点:忘记女孩也要满足小于等于
const int N = 2e4 + 86;
struct egdes
{
int to, nxt, w;
} e[N * 2];
int hd[N * 2], cur[N * 2], tot = 1, st, en;
vi lv;
void add(int x, int y, int w)
{
e[++tot] = (egdes){y, hd[x], w};
hd[x] = tot;
}
int bfs()
{
lv.assign(N, 0);
memcpy(cur, hd, sizeof(hd));
queue<int> q;
q.push(st);
lv[st] = 1;
while (!q.empty())
{
int p = q.front();
q.pop();
for (int eg = hd[p]; eg; eg = e[eg].nxt)
{
int to = e[eg].to, vol = e[eg].w;
if (vol && !lv[to])
{
lv[to] = lv[p] + 1;
q.push(to);
}
}
}
return lv[en];
}
int dfs(int ss, int flow)
{
if (ss == en)
return flow;
int r = flow;
for (int eg = cur[ss]; eg && r; eg = e[eg].nxt)
{
cur[ss] = eg;
int to = e[eg].to, vol = e[eg].w;
if (vol && lv[to] == lv[ss] + 1)
{
int c = dfs(to, min(r, vol));
r -= c;
{
e[eg].w -= c;
e[eg ^ 1].w += c;
}
}
}
return flow - r;
}
int n, k;
vi rim[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> k;
st = 6 * n + 86, en = st + 1;
f(j, 1, n)
{
string s;
cin >> s;
//if(s.length()!=n)cout<<s.length();
f(i, 1, n)
{
if (s[i - 1] == 'Y')
rim[j].pb(i);
else
rim[j + n].pb(i);
}
}
int l=0,r=n;
while (l<r)
{
memset(hd, 0, sizeof(hd));
tot = 1;
int mid=(l+r+1)>>1;
f(i, 1, n)
{
add(st, i, mid);
add(i, st, 0);
add(i, i + 2 * n, k);
add(i + 2 * n, i, 0);
add(i+4*n,i+n,k);
add(i+n,i+4*n,0);
add(i + n, en, mid);
add(en, i + n, 0);
for (auto it : rim[i])
{
add(i, it + n, 1);
add(it + n, i, 0);
}
for (auto it : rim[i + n])
{
add(i + 2 * n, it +4* n, 1);
add(it + 4*n, i + 2 * n, 0);
}
}
LL ans = 0;
while (bfs())
{
ans += dfs(st, 3e8);
}
if (mid * n == ans)
{
l=mid;
}
else r=mid-1;
}
cout <<l;
return 0;
}