太久没搞网络流,又被坑了一发死循环。。(这次是对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 }