zoukankan      html  css  js  c++  java
  • 刷题总结——小凸玩矩阵(scoi)

    题目:

    题目背景

    SCOI2015 DAY1 T1

    题目描述

    小凸和小方是好朋友,小方给了小凸一个 n×m(n≤m)的矩阵 A,并且要求小凸从矩阵中选出 n 个数,其中任意两个数都不能在同一行或者同一列。
    现在小凸想知道,选出的 n 个数中第 k 大的数的最小值是多少。

    输入格式

    第 1 行读入 3 个整数 n,m,k。
    接下来 n 行,每一行有 m 个数字,第 i 行第 j 个数字代表矩阵中第 i 行第 j 列的元素 Ai,j 。

    输出格式

    输出包含一行,为选出的 n 个数中第 k 大数的最小值。

    样例数据 1

    输入  [复制]

     
    2 3 1 
    1 2 4 
    2 4 1

    输出

    1

    样例数据 2

    输入  [复制]

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

    输出

    3

    备注

    【数据范围】
    对于 20% 的数据,1≤n≤m≤9
    对于 40% 的数据,1≤n≤m≤22;1≤n≤12
    对于 100% 的数据,1≤k≤n≤m≤250;1≤Ai,j≤109


    题解:

    二分加最大匹配(网络流/匈牙利)算法,枚举已有的数,然后小于该数的连边建图,以匹配数为n-k为标准二分答案即可

    心得:

    最开始竟然没看出来是二分匹配···哎,从行和列不能重复这个条件明显可以分析出来的··看来对每个条件都要仔细考虑啊···

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=300;
    int n,m,map[N][N],first[N],next[N*N],go[N*N],tot=0,maxx=0,belong[N],k,used[N];
    inline void comb(int a,int b)
    {
      next[++tot]=first[a],first[a]=tot,go[tot]=b;
    }
    inline void clear()
    {
      tot=0;
      memset(first,0,sizeof(first));
      memset(belong,0,sizeof(belong));
      memset(used,0,sizeof(used));
    }
    inline bool find(int u,int T)
    {
      for(int e=first[u];e;e=next[e])
      {
        if(used[go[e]]!=T)
        {
          used[go[e]]=T;
          if(!belong[go[e]]||find(belong[go[e]],T))
          {
            belong[go[e]]=u;
            return true;
          }
        } 
      }
      return false;
    }
    int main()
    {
     // freopen("a.in","r",stdin);
      scanf("%d%d%d",&n,&m,&k);
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {  
          scanf("%d",&map[i][j]);
          maxx=max(maxx,map[i][j]);
        }
      int l=1,r=maxx;
      while(l<=r)
      {
        clear();
        int mid=(l+r)/2;
        for(int i=1;i<=n;i++)
          for(int j=1;j<=m;j++)
            if(map[i][j]<=mid)
              comb(i,j);
        int temp=0;
        for(int i=1;i<=n;i++)      
          if(find(i,i)) temp++;   
        if(temp>=n-k+1)  r=mid-1;
        else l=mid+1;
      }
      cout<<l<<endl;
      return 0;
    }
  • 相关阅读:
    Entity Framework 已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭 异常处理
    MD5加密
    让AutoMapper在你的项目里飞一会儿
    C# SFTP上传与下载
    读取、修改配置文件节点
    C#对数据库的操作(增删改查)
    实现Icommand接口
    wpf创建用户控件(计时器控件)
    用lpeg解析文本语法
    一种简单的客户端更新方案
  • 原文地址:https://www.cnblogs.com/AseanA/p/6668630.html
Copyright © 2011-2022 走看看