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

我是传送门

先看题目,从数列中选第K小,很容易想到二分或者单调队列,但这里单调队列显得不是那么合适。而任意两个数不在一行一列,这符合二分图的定义,所以思路就很明了了,找出所有的值然后去二分找答案。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define oo 0x7f7f7f7f
#define get(x) scanf( "%d", &x )
#define put(x) printf( "%d", x )
#define cln(x) memset( x, 0, sizeof(x) )
using namespace std;

const int R = 255;
int f[R];
int p[R];
int sq[R][R];
int head[R];
int to[R*R];
int next[R*R];
int n, m, k, ans, tot;

void add( int x, int y )
{
    tot++;
    to[tot] = y;
    next[tot] = head[x];
    head[x] = tot;
}

int DFS( int x, int t )
{
    for ( int i = head[x]; i != -1; i = next[i] )
    {
        if ( p[to[i]] != t )
        {
            int y = to[i];
            p[y] = t;
            if ( f[y] == 0 || DFS( f[y], t ) )
            {
                f[y] = x;
                return 1;
            }
        }
    }
    return 0;
}

int solve( int l, int r )
{
    if ( l > r ) return  l;
    int mid = ( l + r ) >> 1;
    ans = 0;
    tot = 0;

    for ( int i = 1; i <= n; i++ )
        head[i] = -1;
    for ( int i = 1; i <= m; i++ )
        p[i] = f[i] = 0;
    for ( int i = 1; i <= n; i++ )
        for ( int j = 1; j <= m; j++ )
            if ( sq[i][j] <= mid )
                add( i, j );
    for ( int i = 1; i <= n; i++ )
        ans += DFS( i, i );

    if ( ans >= n - k + 1 )
        return solve(l, mid - 1);
    else
        return solve( mid + 1, r );
}

int main()
{
    get(n), get(m), get(k);
    for ( int i = 1; i <= n; i++ )
        for ( int j = 1; j <= m; j++ )
        {
            get(sq[i][j]);
            ans = max( ans, sq[i][j] );
        }
    put( solve( 1, ans ) );
    return 0;
}

↑除了MLE所有错误类型都被我弄出来了,真是伤不起Orz

时间: 2024-10-14 20:07:58

BZOJ 4443: 小凸玩矩阵【二分图】的相关文章

BZOJ 4443 小凸玩矩阵

二分+网络流. #include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<algorithm> #define maxn 255 #define maxv 10050 #define maxe 500500 #define inf 1000000007 using namespace std; int n,m,k,g[maxv],nume=1,ma

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<

[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

LibreOJ #2006. 「SCOI2015」小凸玩矩阵

二次联通门 : LibreOJ #2006. 「SCOI2015」小凸玩矩阵 /* LibreOJ #2006. 「SCOI2015」小凸玩矩阵 本来以为是道数据结构题 后来想了想发现不可做 就考虑二分dp判断 推方程推不出来 就考虑用网络流判断了 二分出一个数 将小于这个数的位置的点编号 每行的可行点与下一行可行的点连边 后一边最大流判断可选出的数的个数是否符合要求即可 */ #include <cstdio> #include <iostream> #include <q

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 大的数字的最小值是多少. 输入格式 第一行给出三个整数

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

【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 [Scoi2015]小凸玩矩阵(二分答案+二分图匹配)

[题目链接]http://www.lydsy.com/JudgeOnline/problem.php?id=4443 [题目大意] 从矩阵中选出N个数,其中任意两个数字不能在同一行或同一列 求选出来的N个数中第K大的数字的最小值是多少. [题解] 我们二分这个第k大数字的大小,将其以上的数字全部删除, 在剩余的部分按行列连边,如果二分图匹配的数量大于n-k那么说明该答案可行. [代码] #include <cstdio> #include <algorithm> #include