传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1305
【题解】
把男孩看成点,女孩看成点,一眼就知道是个匹配模型。
把男孩拆成B1,B2,女孩拆成G1,G2
$B1_i ightarrow B2_i, [k]$
$G2_i ightarrow G1_i, [k]$
表示至多跟k个不喜欢的人跳舞。
如果$(i,j)$喜欢,那么$B1_i ightarrow G1_j ,[1]$
否则$B2_i ightarrow G2_j, [1]$
仔细想想发现十分科学。
二分答案$x$,建边$S ightarrow B1_i ,[x]$,$G1_i ightarrow T ,[x]$。
一个j打成i的傻逼错误检查了半天。。
# include <queue> # include <stdio.h> # include <assert.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10, N = 60; const int mod = 1e9+7, inf = 1e9; int n, K; char mp[N][N]; # define B1(x) (x) # define B2(x) ((x) + n) # define G1(x) ((x) + n + n) # define G2(x) ((x) + n + n + n) int S, T, id[M], idn; namespace MF { int head[N * 5], nxt[M], to[M], flow[M], tot = 1; inline void add(int u, int v, int fl) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; flow[tot] = fl; } inline void adde(int u, int v, int fl) { add(u, v, fl), add(v, u, 0); } queue<int> q; int c[N * 5], cur[N * 5]; inline bool bfs() { while(!q.empty()) q.pop(); for (int i=1; i<=T; ++i) c[i] = -1; c[S] = 0; q.push(S); while(!q.empty()) { int top = q.front(); q.pop(); for (int i=head[top]; i; i=nxt[i]) { if(c[to[i]] != -1 || !flow[i]) continue; c[to[i]] = c[top] + 1; q.push(to[i]); if(to[i] == T) return 1; } } return 0; } inline int dfs(int x, int low) { if(x == T) return low; int r = low, fl; for (int i=cur[x]; i; i=nxt[i]) { if(c[to[i]] != c[x] + 1 || !flow[i]) continue; fl = dfs(to[i], min(r, flow[i])); flow[i] -= fl; r -= fl; flow[i^1] += fl; if(flow[i] > 0) cur[x] = i; if(!r) return low; } if(low == r) c[x] = -1; return low-r; } inline int MF() { int ret = 0; while(bfs()) { for (int i=1; i<=T; ++i) cur[i] = head[i]; ret += dfs(S, inf); } return ret; } inline int main(int x) { for (int i=1; i<=idn; ++i) { int s = id[i]^1; flow[s] = x; } int ret = MF(); for (int i=2; i<=tot; i+=2) { flow[i] += flow[i^1]; flow[i^1] = 0; } return ret == x * n; } } int main() { cin >> n >> K; S = n + n + n + n + 1, T = S + 1; for (int i=1; i<=n; ++i) { scanf("%s", mp[i] + 1); for (int j=1; j<=n; ++j) if(mp[i][j] == 'Y') MF :: adde(B1(i), G1(j), 1); else MF :: adde(B2(i), G2(j), 1); } for (int i=1; i<=n; ++i) { MF :: adde(B1(i), B2(i), K); MF :: adde(G2(i), G1(i), K); MF :: adde(S, B1(i), inf); id[++idn] = MF :: tot; MF :: adde(G1(i), T, inf); id[++idn] = MF :: tot; } int l = 0, r = n, mid; while(1) { if(r - l <= 3) { for (int i=r; i>=l; --i) if(MF :: main(i)) { cout << i; return 0; } break; } mid = l+r>>1; if(MF :: main(mid)) l = mid; else r = mid; } assert(0); return 0; }