2018.10.23【SCOI2015】【洛谷P4251】【BZOJ4443】小凸玩矩陣(二分答案)(二分圖匹配)
阿新 • • 發佈:2018-12-17
洛谷傳送門
解析:
並不知道這道題為什麼在洛谷上是紫題,感覺好水啊。
思路:
把行和列分別當做兩部分圖,中間連邊,可以發現這是一個二分圖匹配。
既然要求大值最小,顯然想到二分。那就是第小值最小。
每次二分出一個答案,將所有比它小的邊全部啟用,然後匈牙利找最大匹配,看最後的最大匹配數,如果,則答案過小,下界上移,否則上界下移。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=251;
bool g[N][N];
int a[N][N];
int match[N],vis[N],idx;
int n,m,k;
inline int find(int u){
for(int re v=1;v<=m;++v){
if((vis[v]^idx)&&g[u][v]){
vis[v]=idx;
if(!match[v]||find(match[v])){
match[v]=u;
return true;
}
}
}
return false;
}
inline bool check(int x){
memset(match,0,sizeof match);
for(int re i=1;i<=n;++i)
for(int re j=1;j<= m;++j)g[i][j]=a[i][j]<=x;
++idx;
int cnt=0;
for(int re i=1;i<=n;++i,++idx)if(find(i))++cnt;
return cnt>=n-k+1;
}
int minn=0x3f3f3f3f,maxn=0;
signed main(){
n=getint();
m=getint();
k=getint();
for(int re i=1;i<=n;++i)
for(int re j=1;j<=m;++j){
a[i][j]=getint();
maxn=max(maxn,a[i][j]);
minn=min(minn,a[i][j]);
}
int l=minn,r=maxn;
while(l<r){
int mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
cout<<l;
return 0;
}