题目大意:给一个N*M的矩阵,选出N个数,使得每行没列只选一个数,求第K大的数的最小值是多少?
二分答案,第k大的数<=x,则有N-k+1个数<=k,用二分图判定。
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
int a[][];
void init(){
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
scanf("%d",&a[i][j]);
}
struct node{
int to[],next[],h[],tot;
int g[],tim,vis[];
void init(){
tot=;
memset(h,,sizeof(h));
memset(g,,sizeof(g));
}
void add(int x,int y){
tot++;to[tot]=y;next[tot]=h[x];h[x]=tot;
}
void build(int x){
init();
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
if(a[i][j]<=x)add(i,j);
}
int find(int x){
for(int i=h[x];i;i=next[i]){
int v=to[i];
if(vis[v]==tim)continue;
vis[v]=tim;
if(!g[v]||find(g[v])){
g[v]=x;
return ;
}
}
return ;
}
int solve(){
int tmp=;
for(int i=;i<=n;++i){
++tim;
if(find(i))tmp++;
}
return tmp;
}
}A;
bool jud(int x){
A.build(x);
int ans=A.solve();
return ans>=n-k+;
}
void work(){
int L=,R=1e9;
while(L<R){
int mid=(L+R)>>;
if(jud(mid))R=mid;
else L=mid+;
}
printf("%d\n",L);
}
int main(){
init();
work();
return ;
}