题目
Luogu
LOJ
Acwing
思路
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 610, M = 500010, INF = 2e9;
int n, m, k, S, T, a[310][310];
int h[N], ptr[M], val[M], f[M], idx;
int cur[N], q[N], d[N];
void add(int a, int b, int c) { f[idx] = c, val[idx] = b, ptr[idx] = h[a], h[a] = idx++; }
void add(int a, int b, int c, int d) { add(a, b, c), add(b, a, d); }
bool BFS() {
int hh = 0, tt = -1;
memset(d, -1, sizeof d);
d[S] = 0, q[++tt] = S, cur[S] = h[S];
for (int t = q[hh]; hh <= tt; hh++, t = q[hh])
for (int i = h[t], v = val[i]; i != -1; i = ptr[i], v = val[i]) {
if (d[v] != -1 || !f[i]) continue;
d[v] = d[t] + 1, cur[v] = h[v], q[++tt] = v;
if (v == T) return true;
}
return false;
}
int find(int u, int limit) {
if (u == T) return limit;
int flow = 0;
for (int i = cur[u], v = val[i]; i != -1 && flow < limit; i = ptr[i], v = val[i]) {
cur[u] = i;
if (d[v] == d[u] + 1 && f[i]) {
int t = find(v, min(f[i], limit - flow));
if (!t) d[v] = -1;
f[i] -= t, f[i ^ 1] += t, flow += t;
}
}
return flow;
}
int Dinic() {
int res = 0;
for (int flow = 0; BFS(); flow = 0)
while (flow = find(S, INF)) res += flow;
return res;
}
bool check(int mid) {
memset(h, -1, sizeof h), idx = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
// 连边
if (a[i][j] <= mid)
add(i, j + n, 1, 0);
// 源点汇点连边
for (int i = 1; i <= n; i++) add(S, i, 1, 0);
for (int j = 1; j <= m; j++) add(j + n, T, 1, 0);
int t = Dinic();
return t >= n + 1 - k;
}
int main() {
cin >> n >> m >> k;
S = 0, T = n + m + 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
int l = 1, r = 1e9;
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << r << endl;
return 0;
}