BZOJ 4443 [Scoi2015]小凸玩矩阵(二分答案+二分图匹配)

【题目链接】http://www.lydsy.com/JudgeOnline/problem.php?id=4443

【题目大意】

  从矩阵中选出N个数,其中任意两个数字不能在同一行或同一列
  求选出来的N个数中第K大的数字的最小值是多少。

【题解】

  我们二分这个第k大数字的大小,将其以上的数字全部删除,
  在剩余的部分按行列连边,如果二分图匹配的数量大于n-k那么说明该答案可行。

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int MAX_V=1000;
const int INF=0x3f3f3f3f;
int V,match[MAX_V];
vector<int> G[MAX_V];
bool used[MAX_V];
void add_edge(int u,int v){
    G[u].push_back(v);
    G[v].push_back(u);
}
bool dfs(int v){
    used[v]=1;
    for(int i=0;i<G[v].size();i++){
        int u=G[v][i],w=match[u];
        if(w<0||!used[w]&&dfs(w)){
            match[v]=u;
            match[u]=v;
            return 1;
        }
    }return 0;
}
int bipartite_matching(){
    int res=0;
    memset(match,-1,sizeof(match));
    for(int v=0;v<V;v++){
        if(match[v]<0){
            memset(used,0,sizeof(used));
            if(dfs(v))res++;
        }
    }return res;
}
const int N=300;
int n,m,k,a[N][N];
bool check(int x){
    V=n+m+1;
    for(int i=0;i<V;i++)G[i].clear();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)if(a[i][j]<=x){
            add_edge(i,n+j);
        }
    }return bipartite_matching()>=n-k+1;
}
int main(){
    while(~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]);
        }
        int l=1,r=1000000000,ans=r;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid))r=mid-1,ans=mid;
            else l=mid+1;
        }printf("%d\n",ans);
    }return 0;
}
时间: 2024-12-23 20:02:40

BZOJ 4443 [Scoi2015]小凸玩矩阵(二分答案+二分图匹配)的相关文章

bzoj 4443: [Scoi2015]小凸玩矩阵

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 149  Solved: 81[Submit][Status][Discuss] Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 Output 如题 Samp

4443: [Scoi2015]小秃玩矩阵|二分答案|匈牙利

第K大看成第K小各种WA... 第K大也就是第n?K+1小,所以就可以愉快的二分答案了 二分答案找出比当前答案小的数的位置的坐标,判断一下是否可以选出满足不在同一行同一列的n?K+1个数,然后就可以愉快的跑匈牙利了,对于一个坐标(x,y)如果满足a[x][y]≤当前答案,就把第x行向第y列连边,然后跑匈牙利判断最大匹配是否大于n?K+1 匈牙利真是跑的飞快,然后就卡成rank1 QAQ #include<algorithm> #include<iostream> #include&

4443: [Scoi2015]小凸玩矩阵

4443: [Scoi2015]小凸玩矩阵 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 Output 如题 Sample Input 3 4 2 1 5 6 6 8 3 4 3 6 8 6 3 Sample Output 3 HINT 1<=K&l

【BZOJ4443】[Scoi2015]小凸玩矩阵 二分+二分图最大匹配

[BZOJ4443][Scoi2015]小凸玩矩阵 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 Output 如题 Sample Input 3 4 2 1 5 6 6 8 3 4 3 6 8 6 3 Sample Output 3 HINT 1<

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

#2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 小凸和小方是好朋友,小方给小凸一个 N×M N \times MN×M(N≤M N \leq MN≤M)的矩阵 A AA,要求小凸从其中选出 N NN 个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的 N NN 个数中第 K KK 大的数字的最小值是多少. 输入格式 第一行给出三个整数

【bzoj4443】[Scoi2015]小凸玩矩阵 二分+二分图匹配

题目描述 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. 输入 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 输出 如题 样例输入 3 4 2 1 5 6 6 8 3 4 3 6 8 6 3 样例输出 3 题解 二分+二分图最大匹配 最(第k)大值最小,很容易想到二分答案. 二分一个mid,若满足条件,一定满足:可以选出n-k+1个不

BZOJ 4443: 小凸玩矩阵【二分图】

我是传送门 先看题目,从数列中选第K小,很容易想到二分或者单调队列,但这里单调队列显得不是那么合适.而任意两个数不在一行一列,这符合二分图的定义,所以思路就很明了了,找出所有的值然后去二分找答案. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define oo 0x7f7f7f7f #define get(x) scanf( "%d&q

[Scoi2015]小凸玩矩阵

bzoj 4443: [Scoi2015]小凸玩矩阵 http://www.lydsy.com/JudgeOnline/problem.php?id=4443 Time Limit: 10 Sec  Memory Limit: 128 MB Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N

【bzoj4443】[Scoi2015]小凸玩矩阵

第K大也就是第n-K+1小,所以就可以的二分答案了 (江哥讲过一道类似题) 二分答案找出比当前答案小的数的位置的坐标,判断一下是否可以选出满足不在同一行同一列的n-K+1个数,然后就可以跑匈牙利了,对于一个坐标(x,y)如果满足a[x][y]≤a[x][y]当前答案,就把第x行向第y列连边,然后跑匈牙利判断最大匹配是否大于n-K+1 #include<algorithm> #include<iostream> #include<cstdlib> #include<