一个数对应一行和一列,二分答案,凡是小于等于答案的就连边。如果满足能够取出 \(n - k + 1\) 个不比二分中点 \(mid\) 大的数,那么r = mid,不然l = mid + 1

为什么是要求 \(n - k + 1\) 个不大于答案的数,而不是 \(k\) 个不小于答案的数呢?因为后者无法保证能够取出 \(n\) 个数。比方说:

样例
3 4 2
1 5 6 6
8 3 4 3
6 8 6 3

\(1\) 满足能够取出 \(k\) 个不小于它的数,但如果把它作为第 \(k\) 大的数,就无法找到 \(n - k\) 个比它小的数一并取出。

换言之,如果能够取出 \(n - k - 1\) 个不大于它的数,就一定能够在它取最小值时再取出 \(k\) 个大于等于它的数;如果能够取出 \(k\) 个大于等于它的数,却不一定能够在它取最小值时再取出 \(n - k - 1\) 个小于等于它的数。

#include <cstdio>
#include <cstring>
#include <queue> inline int min(const int& a, const int& b){
return a < b ? a : b;
} inline int max(const int& a, const int& b){
return a > b ? a : b;
} const int MAXN = 5e2 + 19, MAXM = 2.5e5 + 19; struct Edge{
int to, next, c;
}edge[MAXM << 1]; int cnt = -1, head[MAXN]; inline void add(int from, int to, int c){
edge[++cnt].to = to;
edge[cnt].c = c;
edge[cnt].next = head[from];
head[from] = cnt;
} int n, m, k;
int a[MAXN][MAXN]; int dep[MAXN]; int bfs(void){
std::queue<int>q; q.push(0);
std::memset(dep, 0, sizeof dep); dep[0] = 1;
while(!q.empty()){
int node = q.front(); q.pop();
for(int i = head[node]; i != -1; i = edge[i].next)
if(!dep[edge[i].to] && edge[i].c)
dep[edge[i].to] = dep[node] + 1, q.push(edge[i].to);
}
return dep[n + m + 1];
} int dfs(int node, int flow){
if(node == n + m + 1 || !flow)
return flow;
int stream = 0, f;
for(int i = head[node]; i != -1; i = edge[i].next)
if(dep[edge[i].to] == dep[node] + 1 && (f = dfs(edge[i].to, min(flow, edge[i].c)))){
flow -= f, stream += f;
edge[i].c -= f, edge[i ^ 1].c += f;
if(!flow)
break;
}
return stream;
} int dinic(void){
int flow = 0;
while(bfs())
flow += dfs(0, 0x3f3f3f3f);
return flow;
} int main(){
int l = 0x3f3f3f3f, r = 0;
std::scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
std::scanf("%d", &a[i][j]);
l = min(l, a[i][j]), r = max(r, a[i][j]);
}
while(l < r){
int mid = (l + r) >> 1;
std::memset(head, -1, sizeof head), cnt = -1;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if(a[i][j] <= mid)
add(i, j + n, 1), add(j + n, i, 0);
for(int i = 1; i <= n; ++i)
add(0, i, 1), add(i, 0, 0);
for(int j = 1; j <= m; ++j)
add(j + n, n + m + 1, 1), add(n + m + 1, j + n, 0);
if(dinic() >= n - k + 1)
r = mid;
else
l = mid + 1;
}
std::printf("%d\n", l);
return 0;
}

LibreOJ #2006. 「SCOI2015」小凸玩矩阵的更多相关文章

  1. LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配

    #2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  2. loj #2006. 「SCOI2015」小凸玩矩阵

    #2006. 「SCOI2015」小凸玩矩阵   题目描述 小凸和小方是好朋友,小方给小凸一个 N×M N \times MN×M(N≤M N \leq MN≤M)的矩阵 A AA,要求小凸从其中选出 ...

  3. 【LOJ】#2006. 「SCOI2015」小凸玩矩阵

    题解 又是美好的一天,我今天的小目标是LOJ刷题数名次前进两名(虽然巨佬们都是BZOJ千题啊这样的><,我就在LOJ划划水吧,我永远喜欢LOJ 这道题要求K大值最小,又是什么什么大值最小, ...

  4. AC日记——「SCOI2015」小凸玩矩阵 LiBreOJ 2006

    「SCOI2015」小凸玩矩阵 思路: 二分+最大流: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 300 ...

  5. 「SCOI2015」小凸玩矩阵 解题报告

    「SCOI2015」小凸玩矩阵 我好沙茶啊 把点当边连接行和列,在外面二分答案跑图的匹配就行了 我最开始二分方向搞反了,样例没过. 脑袋一抽,这绝壁要费用流,连忙打了个KM 然后wa了,一想这个不是完 ...

  6. 「SCOI2015」小凸玩矩阵

    题目链接 问题分析 题目给了充足的暗示,我们只需要二分答案然后跑匈牙利即可.要相信匈牙利的速度 参考程序 #include <bits/stdc++.h> using namespace ...

  7. 「SCOI2015」小凸玩密室 解题报告

    「SCOI2015」小凸玩密室 虽然有心里在想一些奇奇怪怪的事情的原因,不过还是写太久了.. 不过这个题本身也挺厉害的 注意第一个被点亮的是任意选的,我最开始压根没注意到 \(dp_{i,j}\)代表 ...

  8. loj#2009.「SCOI2015」小凸玩密室

    题目链接 loj#2009. 「SCOI2015」小凸玩密室 题解 树高不会很高<=20 点亮灯泡x,点亮x的一个子树,再点亮x另外的子树, 然后回到x的父节点,点亮父节点之后再点亮父节点的其他 ...

  9. —Libre#2009. 「SCOI2015」小凸玩密室

    #2009. 「SCOI2015」小凸玩密室 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

随机推荐

  1. 使用电脑热点和Fiddler对Android app进行抓包

    如果没有路由器,怎么对app抓包?如果你的电脑可以开热点的话也可以. 打开Fiddler,菜单栏选择Tools->Options->Connections,勾选Allow remote c ...

  2. buuctf——easyjava

    虽然学过Javaweb的开发,但没好好学,所以对Javaweb了解不深 菜的真实 WEB-INF/web.xml泄露 贴一个别人的源码泄露总结ctf/web源码泄露及利用办法[总结中] WEB-INF ...

  3. HDU3173 Dominos

    单向并查集,问至少给几个点可以遍历全图,连通块数量n,入度为0的点的数量m,取max(n,m)~ #include<cstdio> #include<algorithm> #i ...

  4. UDLD(Unidirectional Link Detection)

    1.UDLD(单向链路检测协议)工作原理          为了在生成转发环路之前检测到单向链路,Cisco 设计并实施了 UDLD 协议.UDLD 是与第 1 层 (L1) 机制一起工作以确定链路物 ...

  5. 显ipQQ

    链接:https://pan.baidu.com/s/1l1WN4b3jT8n4e66DH8d-cg 提取码:kjm4

  6. linux kali 的ifconfig命令

    ifconfig命令 1.ifconfig执行页面 root@localhost:/home/zys# ifconfig lo: flags=73<UP,LOOPBACK,RUNNING> ...

  7. python2.7 一个莫名其妙的错误

    先看看错误: Traceback (most recent call last): File "/home/darkchii/文档/PycharmProjects/ml/model.py&q ...

  8. redhat 7.6 流量监控命令、软件(1) ethstatus

    1. 查看1个月内流量,只保留一个月的流量 命令: sar   -n  DEV   -f    /var/log/sa/sa26 RX代表进来的流量,TX代表出去的流量 2.安装查看实时流量软件eth ...

  9. SVN 锁定无法提交命令执行失败

    有个项目使用svn 高版本客户端作业,转换到低版本的环境下,出现锁定,命令执行失败. 使用cleanup 没有效果, 网上建议的svn无法Cleanup解决方法: Step1:到 sqlite官网 ( ...

  10. 02使用GitHub远程仓库

    一.远程库配置 由于本地的GIT仓库和GitHub仓库之间的传输是通过SSH加密的,所以需要以下配置: 1.创建SSH key 为什么GitHub需要SSHKey:根据key来授权,有哪些key可以往 ...