zoukankan      html  css  js  c++  java
  • 二分+二分匹配

    给了一个矩阵 n行m列 选n个数 要保证这n个数不在同行同列,计算出第k大的数最小 , 二分答案,然后我们对于每个a[i][j]<=mid的我们就i和j建立一条边 然后二分求最大匹配必须大于等于n-k-1(因为是第k大 而不是第k小 坑了好久才发现) 

    #include <algorithm>
    #include <stdio.h>
    #include <string.h>
    #include <vector>
    #include <iostream>
    using namespace std;
    const int maxn=100+5;
    struct BPM {
      int n, m;               // 左右顶点个数
      vector<int> G[maxn];    // 邻接表
      int left[maxn];         // left[i]为右边第i个点的匹配点编号,-1表示不存在
      bool T[maxn];           // T[i]为右边第i个点是否已标记
    
      int right[maxn];        // 求最小覆盖用
      bool S[maxn];           // 求最小覆盖用
    
      void init(int n) {
        this->n = n;
        for(int i = 0; i < n; i++) G[i].clear();
      }
    
      void AddEdge(int u, int v) {
        G[u].push_back(v);
      }
    
      bool match(int u){
        S[u] = true;
        for(int i = 0; i < G[u].size(); i++) {
          int v = G[u][i];
          if (!T[v]){
            T[v] = true;
            if (left[v] == -1 || match(left[v])){
              left[v] = u;
              return true;
            }
          }
        }
        return false;
      }
    
      // 求最大匹配
      int solve() {
        memset(left, -1, sizeof(left));
        int ans = 0;
        for(int u = 0; u < n; u++) { // 从左边结点u开始增广
          memset(S, 0, sizeof(S));
          memset(T, 0, sizeof(T));
          if(match(u)) ans++;
        }
        return ans;
      }
    }S;
    int a[maxn][maxn];
    void add(int n,int m,int mid)
    {
         S.init(n);
         for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
              if(a[i][j]<=mid) S.AddEdge(i,j);
    }
    int main()
    {
        int n,m,k;
        int cas;
        scanf("%d",&cas);
        for(int cc=1; cc<=cas; cc++)
            {
                scanf("%d%d%d",&n,&m,&k);
                int L=0,R=0;
                for(int i=0; i<n; i++)
                  for(int j=0; j<m; j++)
                  {
                       scanf("%d",&a[i][j]);
                       R=max(R,a[i][j]);
                  }
                int ans=0;
                while(L<=R)
                    {
                         int mid=(L+R)>>1;
                         add(n,m,mid);
                         int num=S.solve();
                         if(num>=n-k+1){
                            ans=mid; R=mid-1;
                         }else{
                            L=mid+1;
                         }
                    }
                    printf("Case #%d: %d
    ",cc,ans);
            }
        return 0;
    }
    View Code
  • 相关阅读:
    译 PrestaShop开发者指南 第三篇 设置本地安装环境
    译 PrestaShop开发者指南 第二篇 代码规范
    [译]PrestaShop开发者指南 第一篇 基础
    Discuz!X3解读之类引入机制及目录结构
    Discuz的缓存体系
    x3d 规范 在线镜像版
    大容量数据库对表做分割
    链表 队列 堆栈 视频
    How ASP.NET MVC Works?
    SQLServer查看和解决死锁的方法
  • 原文地址:https://www.cnblogs.com/Opaser/p/4782526.html
Copyright © 2011-2022 走看看