二分+二分匹配

给了一个矩阵 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\n",cc,ans);
        }
    return 0;
}

时间: 2024-10-08 09:45:10

二分+二分匹配的相关文章

hiho week 38 P1 : 二分&#183;二分答案

P1 : 二分·二分答案 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 在上一回和上上回里我们知道Nettle在玩<艦これ>,Nettle在整理好舰队之后终于准备出海捞船和敌军交战了.在这个游戏里面,海域是N个战略点(编号1..N)组成,如下图所示其中红色的点表示有敌人驻扎,猫头像的的点表示该地图敌军主力舰队(boss)的驻扎点,虚线表示各个战略点之间的航线(无向边).在游戏中要从一个战略点到相邻战略点需要满足一

hiho week 37 P1 : 二分&#183;二分查找之k小数

P1 : 二分·二分查找之k小数 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很多船位,但船位再多也是有限的.Nettle通过捞船又出了一艘稀有的 船,但是已有的N(1≤N≤1,000,000)个船位都已经有船了.所以Nettle不得不把其中一艘船拆掉来让位给新的船.Nettle思考了很久, 决定随机选择一个k,然后拆掉稀有度第k小的船. 已知

#1128 : 二分&#183;二分查找 ( 两种方法 先排序在二分O(nlogN) + 直接二分+快排思想O(2N) )

#1128 : 二分·二分查找 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Nettle最近在玩<艦これ>,因此Nettle收集了很多很多的船(这里我们假设Nettle氪了很多金,开了无数个船位).去除掉重复的船之后,还剩下N(1≤N≤1,000,000)种不同的船.每一艘船有一个稀有值,任意两艘船的稀有值都不相同,稀有值越小的船越稀有,价值也就越高. Nettle现在通过大建又造出了一艘船,他想知道这艘船是不是重复的.如果是重复的,那么这艘船在Nettle所

hiho#1133 : 二分&#183;二分查找之k小数

#1133 : 二分·二分查找之k小数 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回里我们知道Nettle在玩<艦これ>,Nettle的镇守府有很多船位,但船位再多也是有限的.Nettle通过捞船又出了一艘稀有的船,但是已有的N(1≤N≤1,000,000)个船位都已经有船了.所以Nettle不得不把其中一艘船拆掉来让位给新的船.Nettle思考了很久,决定随机选择一个k,然后拆掉稀有度第k小的船. 已知每一艘船都有自己的稀有度,Nettle现在把所有

hdu1669+二分多重匹配+二分

n个人分成m组,求人数最多的那一组人数的最小值. 每个人肯定只能匹配一个组,但一个组可以匹配多个人,因此属于多重匹配. 我们设置一个limit,表示每组最多能容纳的人数.在dfs(u)寻找u的匹配时,如果某一组vv的人数小于limit,那么可以把u和vv匹配,vv已经匹配的人数+1.否则,当人数已经达到limit,我们对vv的每个匹配做dfs,即寻找增广,若能找到,修改这个匹配,即让vv和u匹配. 然后我们可以二分limit,当u集合(人的集合)中所有点都能找到匹配,则减小limit值,否则只要

zoj 3460 二分+二分图匹配

不错的思想 1 /* 2 大致题意: 3 4 用n个导弹发射塔攻击m个目标.每个发射架在某个时刻只能为 5 一颗导弹服务,发射一颗导弹需要准备t1的时间,一颗导弹从发 6 射到击中目标的时间与目标到发射架的距离有关.每颗导弹发 7 射完成之后发射架需要t2的时间进入下个发射流程.现在问 8 最少需要多少时间可以击毁所有m个目标. 9 10 11 大致思路: 12 二分枚举这个最大时间的最小值,每次按照这个枚举的时间构出 13 二分图,求最大匹配来判定枚举值是否符合要求. 14 15 注意单位,T

bzoj 1014 LCP 二分 Hash 匹配

求同一字符串的两个后缀的最长公共前缀. 将字符串按位置放到Splay中维护(每个节点还维护一下该子树的hash),然后二分前缀的长度,用splay计算出指定范围的hash,按hash是否相等来判断是否相同. 一开始是将字符串看成26进制,加上unsigned long long的自然溢出来计算哈希,但这样Wa掉了,改成27进制就AC了,但我还不知道为什么,望明者相告,谢. 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个不

ZOJ 3460 Missile(二分+ 二分图匹配)

解题思路: 把每一个可发射导弹的时间看成一个发射装置,总共n * m个,然后二分答案 #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <string.h> #include <vector> #include <queue> #include <mat