二分答案,把小于等于该答案的边加入二分图,判断匹配数是否大于等于n-k+1。
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>
#define INF 2147483647
#define N 200500
#define M 400050
using namespace std;
struct Node {int u,cap,rec;};
vector<Node> e[N];
int n,m,p[N],a[M],b[M],v[M],S,T,lim,ans;
int row[N],col[N],tot;
int map[255][255],k;
int cnt;
void add_Node(int a,int b,int v)
{
Node tmp;
tmp.u = b;
tmp.cap = v;
tmp.rec = e[b].size();
e[a].push_back(tmp);
tmp.u = a;
tmp.cap = 0;
tmp.rec = e[a].size() - 1;
e[b].push_back(tmp);
}
bool BFS()
{
bool flag = false;
memset(p,0,sizeof(p));
queue<int> q;
q.push(S);
p[S] = 1;
while (!q.empty()) {
int u = q.front();q.pop();
if (u == T) flag = true;
for (int i=0;i<(int)e[u].size();i++) {
int v = e[u][i].u;
int cp = e[u][i].cap;
if (p[v] == 0 && cp > 0) {
q.push(v);
p[v] = p[u] + 1;
}
}
}
return flag;
}
int DFS(int u,int flow) {
if (u == T) return flow;
int g = 0 , f = flow;
for (int i=0;i<(int)e[u].size();i++) {
int v = e[u][i].u;
int cp = e[u][i].cap;
int tmp = 0;
if (p[v] == p[u]+1 && cp > 0 && (tmp = DFS(v,min(f,cp))) > 0) {
g += tmp;
f -= tmp;
e[u][i].cap -= tmp;
int rc = e[u][i].rec;
e[v][rc].cap += tmp;
}
}
return g;
}
bool g(int x) {
for (int i=1;i<=tot;i++) e[i].clear();
for (int i=1;i<=n;i++) add_Node(S,row[i],1);
for (int i=1;i<=m;i++) add_Node(col[i],T,1);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) if (map[i][j] <= x)
add_Node(row[i],col[j],1);
int flow = 0;
while (BFS()) flow += DFS(S,INF);
return flow >= n-k+1;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) scanf("%d",&map[i][j]);
S = ++tot; T = ++tot;
for (int i=1;i<=n;i++) row[i] = ++tot;
for (int i=1;i<=m;i++) col[i] = ++tot;
int l = 0 , r = 1e9;
while (l < r) {
int mid = (l + r) >> 1;
if (g(mid)) r = mid; else l = mid + 1;
}
printf("%d\n",l);
return 0;
}