• [SCOI2015]小凸玩矩阵


    题目:洛谷P4251、BZOJ4443。

    题目大意:
    有一个(n imes m(nleq m))的矩阵,要选出n个数,使得这n个数既不同行也不同列。问选的数中第k大的数最小可以是多少。
    解题思路:
    首先二分答案,然后只要判断,是否能选择至少n-k+1个数,它们的值都不超过当前的答案。
    然后很简单,对每个小于等于当前答案的数,行向列连边。做二分图匹配即可。
    时间复杂度(n^2log)级别。

    C++ Code:

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    int n,m,k;
    inline int readint(){
        int c=getchar(),d=0;
        for(;!isdigit(c);c=getchar());
        for(;isdigit(c);c=getchar())
        d=(d<<3)+(d<<1)+(c^'0');
        return d;
    }
    int p[252][252],a[252][252],dy[252],vis[252];
    int dfs(int u){
        for(int i=1;i<=m;++i)
        if(p[u][i]&&!vis[i]){
            vis[i]=1;
            if(!dy[i]||dfs(dy[i])){
                dy[i]=u;
                return 1;
            }
        }
        return 0;
    }
    bool ok(int x){
        for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
        p[i][j]=a[i][j]<=x;
        memset(dy,0,sizeof dy);
        int ans=0;
        for(int i=1;i<=n;++i){
            memset(vis,0,sizeof vis);
            ans+=dfs(i);
        }
        return ans>=n-k+1;
    }
    int main(){
        n=readint(),m=readint(),k=readint();
        for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
        a[i][j]=readint();
        int l=0,r=0x3f3f3f3f,ans=0x3f3f3f3f;
        while(l<=r){
            int mid=l+r>>1;
            if(ok(mid))r=mid-1,ans=mid;else l=mid+1;
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Linux运维笔记
    回到顶部过渡js代码
    好想你红枣
    鼠标点击区域问题
    ie6 hover 子元素无效bug
    IE6和7下text-indent导致inline-block标签消失的bug
    星星评分js代码
    洛谷P3147 [USACO16OPEN]262144 2048 合并 倍增 动归 递推
    洛谷P1114 “非常男女”计划
    洛谷P1108 低价购买 动态规划
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9288490.html
Copyright © 2020-2023  润新知