二分+二分图匹配
题目转化为求k个行列不相交的数,最小化最大值。二分,行列看成二分图,进行匹配即可。
坑爹,第k大是从大的开始算的第k个。我语文好差呀。。。
#include<cstdio>
#include<cstring>
#define N 255
using namespace std;
namespace runzhe2000
{
int n, m, k, a[N][N], last[N], vis[N], mat[N], ecnt;
struct edge{int next, to;}e[N*N];
void addedge(int a, int b)
{
e[++ecnt] = (edge){last[a], b};
last[a] = ecnt;
}
bool match(int x)
{
for(int i = last[x]; i; i = e[i].next)
{
int y = e[i].to;
if(vis[y])continue;
vis[y] = 1;
if(!mat[y] || match(mat[y]))
{
mat[y] = x;
return 1;
}
}
return 0;
}
bool check(int lim)
{
memset(last,0,sizeof(last));
memset(mat,0,sizeof(mat));
ecnt = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(a[i][j] <= lim)
addedge(i, j);
int ans = 0;
for(int i = 1; i <= n; i++)
{
memset(vis,0,sizeof(vis));
if(match(i))ans++;
}
return ans >= k;
}
void main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%d",&a[i][j]);
k = n - k + 1;
int l = 0, r = 1e9;
for(; l < r; )
{
int mid = (l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d\n",l);
}
}
int main()
{
runzhe2000::main();
}