bzoj4443: [Scoi2015]小凸玩矩阵

太久没搞网络流,又被坑了一发死循环。。(这次是对cur[]初始化没对。以后直接for S到T不就好了嘛!)

先看数据量。诶,才250,肯定n三方。搜索不行,dp不行,贪心不行,二分图网络流?恩,有可能,先放一边去。

然而正解就是二分+二分图匹配。

二分答案,二分图匹配看是否存在大等n-k+1个匹配。

基本上每当题目中有限制不能同行不能同列的时候都是二分图左边为行,右边为列来匹配的。(我怎么就是不长记性呢,又被坑了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define INF 1e9+5
 4 #define N 70005
 5 int n,m,k,d[N],cur[N],S,T,cnt,z[255][255],head[N];
 6 bool vis[N];
 7 queue<int>q;
 8 struct edges{
 9     int fr,to,cap,flow,next;
10 }e[4*N];
11 void inser(int u,int v,int c){
12     e[cnt]=(edges){u,v,c,0,head[u]};head[u]=cnt++;
13     e[cnt]=(edges){v,u,0,0,head[v]};head[v]=cnt++;
14 }
15 bool bfs(){
16     memset(vis,0,sizeof(vis));
17     vis[S]=1; q.push(S); d[S]=0;
18     while(!q.empty()){
19         int x=q.front(); q.pop();
20         for(int i=head[x];i>=0;i=e[i].next)
21             if(!vis[e[i].to] && e[i].cap>e[i].flow) vis[e[i].to]=1,d[e[i].to]=d[x]+1,q.push(e[i].to);
22     }
23     return vis[T];
24 }
25 int dfs(int x,int a){
26     if(x==T || !a) return a;
27     int f,flow=0;
28     for(int& i=cur[x];i>=0;i=e[i].next)
29         if(d[e[i].to]==d[x]+1 && (f=dfs(e[i].to,min(a,e[i].cap-e[i].flow)))>0){
30           e[i].flow+=f; flow+=f; e[i^1].flow-=f; a-=f;
31         if(!a) break;
32         }
33     return flow;
34 }
35 int maxflow(){
36     int flow=0;
37     while(bfs()){
38         for(int i=S;i<=T;i++) cur[i]=head[i];
39         flow+=dfs(S,INF);
40     }
41     return flow;
42 }
43 void build(int x){
44     memset(head,-1,sizeof(head)); cnt=0;
45     for(int i=1;i<=n;i++) inser(S,i,1);
46     for(int i=1;i<=m;i++) inser(i+n,T,1);
47     for(int i=1;i<=n;i++)
48        for(int j=1;j<=m;j++)
49          if(z[i][j]<=x) inser(i,j+n,1);
50 }
51 int main(){
52     scanf("%d%d%d",&n,&m,&k);
53     S=0; T=n+m+1;
54     for(int i=1;i<=n;i++)
55        for(int j=1;j<=m;j++)
56           scanf("%d",&z[i][j]);
57     int l=1,r=INF;
58     while(l<r){
59         int mid=(l+r)>>1; build(mid);
60         if(maxflow()<n-k+1) l=mid+1;
61         else r=mid;
62     }
63     printf("%d\n",l);
64     return 0;
65 }
时间: 2024-10-25 06:15:05

bzoj4443: [Scoi2015]小凸玩矩阵的相关文章

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

[BZOJ4443][Scoi2015]小凸玩矩阵 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 Output 如题 Sample Input 3 4 2 1 5 6 6 8 3 4 3 6 8 6 3 Sample Output 3 HINT 1<

[Scoi2015]小凸玩矩阵

bzoj 4443: [Scoi2015]小凸玩矩阵 http://www.lydsy.com/JudgeOnline/problem.php?id=4443 Time Limit: 10 Sec  Memory Limit: 128 MB Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N

4443: [Scoi2015]小凸玩矩阵

4443: [Scoi2015]小凸玩矩阵 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 Output 如题 Sample Input 3 4 2 1 5 6 6 8 3 4 3 6 8 6 3 Sample Output 3 HINT 1<=K&l

【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个不

bzoj 4443: [Scoi2015]小凸玩矩阵

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 149  Solved: 81[Submit][Status][Discuss] Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. Input 第一行给出三个整数N,M,K 接下来N行,每行M个数字,用来描述这个矩阵 Output 如题 Samp

【bzoj4443】[Scoi2015]小凸玩矩阵

第K大也就是第n-K+1小,所以就可以的二分答案了 (江哥讲过一道类似题) 二分答案找出比当前答案小的数的位置的坐标,判断一下是否可以选出满足不在同一行同一列的n-K+1个数,然后就可以跑匈牙利了,对于一个坐标(x,y)如果满足a[x][y]≤a[x][y]当前答案,就把第x行向第y列连边,然后跑匈牙利判断最大匹配是否大于n-K+1 #include<algorithm> #include<iostream> #include<cstdlib> #include<

BZOJ 4443 [Scoi2015]小凸玩矩阵(二分答案+二分图匹配)

[题目链接]http://www.lydsy.com/JudgeOnline/problem.php?id=4443 [题目大意] 从矩阵中选出N个数,其中任意两个数字不能在同一行或同一列 求选出来的N个数中第K大的数字的最小值是多少. [题解] 我们二分这个第k大数字的大小,将其以上的数字全部删除, 在剩余的部分按行列连边,如果二分图匹配的数量大于n-k那么说明该答案可行. [代码] #include <cstdio> #include <algorithm> #include

BZOJ4443:[SCO2015]小凸玩矩阵

题目大意:给一个N*M的矩阵,选出N个数,使得每行没列只选一个数,求第K大的数的最小值是多少? 二分答案,第k大的数<=x,则有N-k+1个数<=k,用二分图判定. #include<bits/stdc++.h> using namespace std; int n,m,k; int a[255][255]; void init(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;++i) f

LibreOJ #2006. 「SCOI2015」小凸玩矩阵

二次联通门 : LibreOJ #2006. 「SCOI2015」小凸玩矩阵 /* LibreOJ #2006. 「SCOI2015」小凸玩矩阵 本来以为是道数据结构题 后来想了想发现不可做 就考虑二分dp判断 推方程推不出来 就考虑用网络流判断了 二分出一个数 将小于这个数的位置的点编号 每行的可行点与下一行可行的点连边 后一边最大流判断可选出的数的个数是否符合要求即可 */ #include <cstdio> #include <iostream> #include <q