https://www.lydsy.com/JudgeOnline/problem.php?id=4443
看到第K大的最小,想到二分
那么二分一个第K大值mid,小于等于mid的元素全都连边,然后求二分图最大匹配,如果匹配的超过n-k+1,那么就是可行的
卧槽我今天突然发现vis数组是m对于右边的点,所以长度应该是m,而不是n。。。。WA了好久
#include<bits/stdc++.h>
using namespace std;
const int maxl=510;
int n,m,k,cnt,ans,mi,mx;
int match[maxl],ehead[maxl];
int a[maxl][maxl];
struct ed
{
int to,nxt;
}e[maxl*maxl];
bool vis[maxl];
inline void add(int u,int v)
{
e[++cnt].to=v;e[cnt].nxt=ehead[u];ehead[u]=cnt;
}
inline void prework()
{
scanf("%d%d%d",&n,&m,&k);
k=n-k+1;
mi=2e9;mx=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
mx=max(a[i][j],mx);
mi=min(a[i][j],mi);
}
}
inline bool dfs(int u)
{
int v;
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
if(!vis[v])
{
vis[v]=true;
if(!match[v] || dfs(match[v]))
{
match[v]=u;
return true;
}
}
}
return false;
}
inline bool jug(int mid)
{
for(int i=1;i<=n;i++)
ehead[i]=0;
for(int i=1;i<=m;i++)
match[i]=0;
cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]<=mid)
add(i,j);
int sum=0;
for(int i=1;i<=n;i++)
{
memset(vis,false,sizeof(bool)*(m+1));
if(dfs(i))
sum++;
}
return sum>=k;
}
inline void mainwork()
{
int l=0,r=1e9,mid;
while(l+1<r)
{
mid=(l+r)>>1;
if(jug(mid))
r=mid;
else
l=mid;
}
if(jug(l))
ans=l;
else
ans=l+1;
}
inline void print()
{
printf("%d",ans);
}
int main()
{
prework();
mainwork();
print();
return 0;
}