LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配

Posted GeekZRF

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配相关的知识,希望对你有一定的参考价值。

#2006. 「SCOI2015」小凸玩矩阵

内存限制:256 MiB时间限制:1000 ms标准输入输出
题目类型:传统评测方式:文本比较
上传者: 匿名

题目描述

小凸和小方是好朋友,小方给小凸一个 N×M N \times MN×M(N≤M N \leq MNM)的矩阵 A AA,要求小凸从其中选出 N NN 个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的 N NN 个数中第 K KK 大的数字的最小值是多少。

输入格式

第一行给出三个整数 N NN、M MM、K KK。
接下来 N NN 行,每行 M MM 个数字,用来描述这个矩阵。

输出格式

输出选出来的 N NN 个数中第 K KK 大的数字的最小值。

样例

样例输入

3 4 2
1 5 6 6 
8 3 4 3
6 8 6 3

样例输出

3

数据范围与提示

1≤K≤N≤M≤250,1≤Ai,j≤109 1 \leq K \leq N \leq M \leq 250, 1 \leq A_{i, j} \leq 10 ^ 91KNM250,1A?i,j??10?9??

 

题目链接:https://loj.ac/problem/2006

题意:选出n个行列不相同的数,使得第k大最小。

思路:二分答案+二分匹配。二分答案,然后对行和列进行二分匹配,a[i][j]<=mid的最大匹配与n-k+1进行比较。

代码:

技术分享
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int maxn=300,maxm=1e5+100,inf=0x3f3f3f3f,mod=1e9+7;
const ll INF=1e18+7;
int n,m,k;
ll a[maxn][maxn];
vector<int>G[maxn];
int match[maxn];
int used[maxn];
bool dfs(int u,ll mid)
{
    for(int v=1; v<=m; v++)
    {
        if(a[u][v]>mid) continue;
        if(used[v]) continue;
        used[v]=true;
        if(match[v]<0||dfs(match[v],mid))
        {
            match[v]=u;
            return true;
        }
    }
    return false;
}
bool check(ll mid)
{
    int res=0;
    memset(match,-1,sizeof(match));
    for(int i=1; i<=n; i++)
    {
        memset(used,false,sizeof(used));
        res+=dfs(i,mid);
    }
    //cout<<res<<endl;
    return res>=n-k+1?1:0;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    ll l=INF,r=0;
    for(int i=1; i<=n; i++)
    {
        ll mmin=INF,mmax=0;
        for(int j=1; j<=m; j++)
        {
            scanf("%d",&a[i][j]);
            l=min(l,a[i][j]),r=max(r,a[i][j]);
        }
    }
    ll ans=-1;
    while(l<=r)
    {
        ll mid=(l+r)/2;
        //cout<<l<<" "<<r<<" "<<mid<<endl;
        if(check(mid)) r=mid-1,ans=mid;
        else l=mid+1;
    }
    printf("%lld\n",ans);
    return 0;
}
二分答案+二分比配

 

以上是关于LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配的主要内容,如果未能解决你的问题,请参考以下文章

LibreOJ #2007. 「SCOI2015」国旗计划

LibreOJ #2009. 「SCOI2015」小凸玩密室

AC日记——「SCOI2015」情报传递 LiBreOJ 2011

AC日记——「SCOI2015」国旗计划 LiBreOJ 2007

LibreOJ #2016. 「SCOI2016」美味

LibreOJ #2012. 「SCOI2016」背单词