bzoj4443: [Scoi2015]小凸玩矩阵
Posted Izaya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于bzoj4443: [Scoi2015]小凸玩矩阵的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ4443[Scoi2015]小凸玩矩阵 二分+二分图最大匹配
bzoj4443[Scoi2015]小凸玩矩阵 二分+二分图匹配