bzoj 4443 [Scoi2015]小凸玩矩阵 网络流,二分
[Scoi2015]小凸玩矩阵
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1564 Solved: 734
[Submit][Status][Discuss]
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
1 5 6 6
8 3 4 3
6 8 6 3
Sample Output
3
HINT
1<=K<=N<=M<=250,1<=矩阵元素<=10^9
判断是否能取出N-K+1个小于等于ans的数
但是能取出N-K+1个小于等于ans的数,不代表能取出K个大于等于ans的数呀
注意,最后得到的ans是最小的存在N-K个比它小的数的数
如果连最小的ans都取不到,那么更大的ans也取不到呀
判断的话若(i,j)小于等于x,则第i行向第j列连边,然后跑最大流看是否大于等于n-k+1即可
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<ctime> 7 #include<algorithm> 8 #include<iomanip> 9 #include<vector> 10 #include<stack> 11 #include<queue> 12 #include<map> 13 #include<set> 14 #include<bitset> 15 using namespace std; 16 #define MAXN 1010 17 #define MAXM 150010 18 #define ll long long 19 #define INF 1000000000 20 #define MOD 1000000007 21 #define eps 1e-8 22 struct vec{ 23 int to; 24 int fro; 25 int v; 26 }; 27 vec mp[MAXM]; 28 int tai[MAXN],cnt=1; 29 int q[MAXM],hd,tl; 30 int s,t; 31 int cur[MAXN]; 32 int d[MAXN]; 33 int ans; 34 inline void be(int x,int y,int z){ 35 mp[++cnt].to=y; 36 mp[cnt].fro=tai[x]; 37 tai[x]=cnt; 38 mp[cnt].v=z; 39 } 40 inline void bse(int x,int y,int z){ 41 be(x,y,z); 42 be(y,x,0); 43 } 44 bool bfs(){ 45 int i,x,y; 46 hd=tl=0; 47 q[tl++]=s; 48 memset(d,0,sizeof(d)); 49 d[s]=1; 50 while(hd!=tl){ 51 x=q[hd++]; 52 for(i=tai[x];i;i=mp[i].fro){ 53 y=mp[i].to; 54 if(!d[y]&&mp[i].v){ 55 d[y]=d[x]+1; 56 q[tl++]=y; 57 } 58 } 59 } 60 return d[t]; 61 } 62 int dfs(int x,int mx){ 63 if(x==t){ 64 return mx; 65 } 66 int y; 67 ll re=0,tmp; 68 for(int &i=cur[x];i;i=mp[i].fro){ 69 y=mp[i].to; 70 if(d[y]==d[x]+1&&mp[i].v){ 71 tmp=dfs(y,min(mx,mp[i].v)); 72 re+=tmp; 73 mx-=tmp; 74 mp[i].v-=tmp; 75 mp[i^1].v+=tmp; 76 if(!mx){ 77 return re; 78 } 79 } 80 } 81 if(!re){ 82 d[x]=0; 83 } 84 return re; 85 } 86 int n,m,a[260][260],k; 87 bool OK(int x){ 88 int i,j; 89 s=n+m+1; 90 t=s+1; 91 memset(tai,0,sizeof(tai)); 92 cnt=1; 93 for(i=1;i<=n;i++){ 94 for(j=1;j<=m;j++){ 95 if(a[i][j]<=x){ 96 bse(i,n+j,1); 97 } 98 } 99 } 100 for(i=1;i<=n;i++){ 101 bse(s,i,1); 102 } 103 for(i=1;i<=m;i++){ 104 bse(n+i,t,1); 105 } 106 int flow=0; 107 while(bfs()){ 108 for(i=1;i<=t;i++){ 109 cur[i]=tai[i]; 110 } 111 flow+=dfs(s,INF); 112 } 113 return flow>=n-k+1; 114 } 115 int main(){ 116 int i,j; 117 scanf("%d%d%d",&n,&m,&k); 118 for(i=1;i<=n;i++){ 119 for(j=1;j<=m;j++){ 120 scanf("%d",&a[i][j]); 121 } 122 } 123 int l=0,r=INF; 124 int ans; 125 while(l<=r){ 126 int mid=l+r>>1; 127 if(OK(mid)){ 128 ans=mid; 129 r=mid-1; 130 }else{ 131 l=mid+1; 132 } 133 } 134 printf("%d\n",ans); 135 return 0; 136 } 137 138 /* 139 140 */