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<=N<=M<=250,1<=矩阵元素<=10^9

ACTY真大神!!!(大家有空去bzoj上搜搜看)

—————以下题解——————

很容易看出是二分答案。。

题目中说是第k大,其实是第n-k+1小(一直看错)。。。

我们每次验证mid时把矩阵中<=mid的数关于坐标连边,跑一遍二分图最大匹配,判断最大匹配数是否大于n-k+1。。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=255;
int n,m,k,i,j,ans,a[N][N],f[N],p[N];
int tot,head[N],Next[N*N],to[N*N];
void add(int x,int y)
{
    tot++;
    to[tot]=y;
    Next[tot]=head[x];
    head[x]=tot;
}
int dfs(int x,int T)
{
    int i;
    for(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 erfen(int l,int r)
{
    if(l>r) return l;
    int mid=(l+r)>>1,i,j,ans=0;
    tot=0;
    for(i=1;i<=n;i++)
        head[i]=-1;
    for(i=1;i<=m;i++)
        p[i]=f[i]=0;
    for(i=1;i<=n;i++)
     for(j=1;j<=m;j++)
     if(a[i][j]<=mid) add(i,j);
    for(i=1;i<=n;i++)
        ans+=dfs(i,i);
    if(ans>=n-k+1) return erfen(l,mid-1);else
    return erfen(mid+1,r);
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=n;i++)
     for(j=1;j<=m;j++)
    {
        scanf("%d",&a[i][j]);
        ans=max(ans,a[i][j]);
    }
    cout<<erfen(1,ans);
    return 0;
}
时间: 2024-10-12 03:39:33

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

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

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

[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]小凸玩矩阵 二分+二分图最大匹配

[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<

【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个不

【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<

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&

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

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

bzoj4443: [Scoi2015]小凸玩矩阵

太久没搞网络流,又被坑了一发死循环..(这次是对cur[]初始化没对.以后直接for S到T不就好了嘛!) 先看数据量.诶,才250,肯定n三方.搜索不行,dp不行,贪心不行,二分图网络流?恩,有可能,先放一边去. 然而正解就是二分+二分图匹配. 二分答案,二分图匹配看是否存在大等n-k+1个匹配. 基本上每当题目中有限制不能同行不能同列的时候都是二分图左边为行,右边为列来匹配的.(我怎么就是不长记性呢,又被坑了 1 #include<bits/stdc++.h> 2 using namesp