题意:一个n*m的矩阵(n<=m<=250),要求选出n个数(每行,每列最多选一个),求第k大数的最小值。

首先第k大的意思是从大到小的第k个数(我读错了,WA了一次还以为算法不对...)

然后第k大最小不好直接做.考虑二分答案.

二分答案的单调性在于,如果不能选出n-k+1个小于等于i的不同行列的数,那么最终的答案大于i,否则最终的答案小于等于i。

判定的时候将每一行看作一个点,每一列也看作一个点,每个位置A[i][j](A[i][j]小于等于判定的答案ans)代表一条第i行和第j行之间的边。(这种二维矩阵每一行怎么样怎么样每一列怎么样怎么样的题常常可以转化成二分图去考虑)。

最后二分出一个i,使得我们可以选出n-k+1个小于等于i的数但不能选出n-k+1个小于等于(i-1)的数,这个i就是答案.

这里有一点问题,就是我们虽然可以选出n-k+1个小于等于i的数,但似乎并没有保证可以选出k-1个大于i的数.因此我在读错题WA了一发之后开始怀疑算法正确性。

所幸,随便选出剩下k-1个数一定可以保证第k大的数字是i.

证明如下:

首先,我们选出所有数字之后,不可能选出n-k+1个小于等于(i-1)的数(否则与二分的结果相违背)。也就是说,我们在选出n-k+1个小于等于i的数之后,随便选剩下的k-1个数字,最终选出的全部数字中至少有k个大于等于i.

于是我们有两个条件:全部数字中,至少有n-k+1个小于等于i(二分条件保证可以先选出n-k+1个这样的数,这个条件等价于从小到大第n-k+1个数也就是从大到小第k个数一定小于等于i),至少有k个大于等于i(也就是说从大到小第k个数一定大于等于i),那么第k大的数既小于等于i又大于等于i,所以第k大的数只能是i,这样就没有问题了。

(似乎别人的题解都觉得这是显然的)

(写了个dinic结果比别人的匈牙利慢好多)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
int n,m,k;
int a[maxn][maxn];
struct edge{
int to,next,w;
}lst[maxn*maxn*];int len=,first[maxn*],_first[maxn*];
void addedge(int a,int b,int w){
lst[len].to=b;lst[len].next=first[a];lst[len].w=w;first[a]=len++;
lst[len].to=a;lst[len].next=first[b];lst[len].w=;first[b]=len++;
}
int s,t;
int q[maxn*],vis[maxn*],T,dis[maxn*],head,tail;
bool bfs(){
vis[s]=++T;head=tail=;
q[tail++]=s;dis[s]=;
while(head!=tail){
int x=q[head++];
for(int pt=first[x];pt!=-;pt=lst[pt].next){
if(lst[pt].w&&vis[lst[pt].to]!=T){
vis[lst[pt].to]=T;dis[lst[pt].to]=dis[x]+;
q[tail++]=lst[pt].to;
}
}
}
if(vis[t]==T)memcpy(_first,first,sizeof(first));
return vis[t]==T;
}
int dfs(int x,int lim){
if(x==t)return lim;
int flow=,a;
for(int pt=_first[x];pt!=-;pt=lst[pt].next){
_first[x]=pt;
if(lst[pt].w&&dis[lst[pt].to]==dis[x]+&&(a=dfs(lst[pt].to,min(lst[pt].w,lim-flow)))){
lst[pt].w-=a;lst[pt^].w+=a;flow+=a;
if(flow==lim)break;
}
}
return flow;
}
int dinic(){
int ans=,x;
while(bfs())
while(x=dfs(s,0x7f7f7f7f))ans+=x;
return ans;
}
bool check(int ans){
memset(first,-,sizeof(first));len=;
s=;t=n+m+;
for(int i=;i<=n;++i){
addedge(s,i,);
}
for(int i=;i<=m;++i){
addedge(n+i,t,);
}
for(int i=;i<=n;++i){
for(int j=;j<=m;++j){
if(a[i][j]<=ans)addedge(i,n+j,);
}
}
return dinic()>=k;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
k=n-k+;
for(int i=;i<=n;++i){
for(int j=;j<=m;++j){
scanf("%d",&a[i][j]);
}
}
int l=,r=;
while(l<=r){
int mid=(l+r)>>;
if(check(mid)){
r=mid-;
}else{
l=mid+;
}
}
printf("%d\n",r+);
return ;
}

bzoj4443[SCOI2015]小凸玩矩阵的更多相关文章

  1. 2018.06.30 BZOJ4443: [Scoi2015]小凸玩矩阵(二分加二分图匹配)

    4443: [Scoi2015]小凸玩矩阵 Time Limit: 10 Sec Memory Limit: 128 MB Description 小凸和小方是好朋友,小方给小凸一个N*M(N< ...

  2. bzoj4443 SCOI2015 小凸玩矩阵 matrix

    传送门:bzoj4443 题解 很水的一道网络流,显然可以二分答案,然后我们希望第\(k\)大尽量小,那么对于一个\(mid\),我们应尽量选择更小的,然后跑二分图最大匹配来验证. code

  3. 【BZOJ4443】[Scoi2015]小凸玩矩阵 二分+二分图最大匹配

    [BZOJ4443][Scoi2015]小凸玩矩阵 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或 ...

  4. BZOJ_4443_[Scoi2015]小凸玩矩阵_二分+二分图匹配

    BZOJ_4443_[Scoi2015]小凸玩矩阵_二分+二分图匹配 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个 ...

  5. 【BZOJ4443】小凸玩矩阵(二分答案,二分图匹配)

    [BZOJ4443]小凸玩矩阵(二分答案,二分图匹配) 题面 BZOJ Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两 ...

  6. BZOJ 4443: [Scoi2015]小凸玩矩阵 最大流

    4443: [Scoi2015]小凸玩矩阵 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4443 Description 小凸和小方是好 ...

  7. bzoj 4443 [Scoi2015]小凸玩矩阵 网络流,二分

    [Scoi2015]小凸玩矩阵 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1564  Solved: 734[Submit][Status][Di ...

  8. 【bzoj4443】【[Scoi2015]小凸玩矩阵】二分+二分图最大匹配

    (上不了p站我要死了,侵权度娘背锅) Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸 ...

  9. [bzoj4443] [loj#2006] [洛谷P4251] [Scoi2015]小凸玩矩阵

    Description 小凸和小方是好朋友,小方给小凸一个 \(N \times M\)( \(N \leq M\) )的矩阵 \(A\) ,要求小秃从其中选出 \(N\) 个数,其中任意两个数字不能 ...

随机推荐

  1. JS高程5.引用类型(4)Array类型的各类方法

    一.转换方法 所有的对象都具有toLocaleString(),toString()和valueOf()方法.调用toString()方法会返回由数组中的每个值的字符串拼接而成的一个以逗号分隔的字符串 ...

  2. JS高程4.变量,作用域和内存问题(3)垃圾收集

    JavaScript的自动垃圾收集机制 执行环境会负责管理代码执行过程中使用的内存,编写JavaScript程序时,所需内存的分配以及无用内存的回收完全实现自动管理. 原理: 找出那些不再继续使用的变 ...

  3. Sencha, the nightmare!

    基础 创建一个应用程序 sencha -sdk /path/to/sdk generate app %name% /path/to/app 跑起来 cd /path/to/app sencha app ...

  4. 拖拽手势和清扫手势冲突时(UIPanGestureRecognizer和UISwipeGestureRecognizer冲突时)

    故事发生在这样的情境上:给整个控制器添加了一个拖拽手势,然后又在控制上的每个Cell上加了左滑清扫手势,然后问题来了:只有拖拽手势起作用,而左滑手势没有效果了,然后怎么解决这个问题呢!先上图: 当给整 ...

  5. Android中的AlertDialog使用示例五(自定义对话框)

    在Android开发中,我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框,AlertDialog实现方法为建造者模式. ...

  6. 腾讯开放平台 手机QQ登录 错误码:110406 解决办法

    作者:Panda Fang 出处:http://www.cnblogs.com/lonkiss/p/4204284.html 原创文章,转载请注明作者和出处,未经允许不可用于商业营利活动 腾讯开发平台 ...

  7. 脱离spring集成cxf(基于nutz框架)

    什么是webService WebService是一种跨编程语言和跨操作系统平台的远程调用技术. 理论资料: http://blog.csdn.net/wooshn/article/details/8 ...

  8. php使用microtime(true)查看代码执行时间

    microtime() 函数返回当前 Unix 时间戳和微秒数. 如果带个 true 参数, 返回的将是一个浮点类型 round() 取出小数点后 3 位 $t1 = microtime(true); ...

  9. Python来做应用题及思路

    Python来做应用题及思路 最近找工作头疼没事就开始琢磨python解应用题应该可以,顺便还可以整理下思路当然下面的解法只是个人理解,也欢迎大佬们给意见或者指点更好的解决办法等于优化代码了嘛,也欢迎 ...

  10. Apache主配置文件httpd.conf 详解

    Apache的主配置文件:/etc/httpd/conf/httpd.conf 默认站点主目录:/var/www/html/ Apache服务器的配置信息全部存储在主配置文件/etc/httpd/co ...