图论(网络流):[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
1 5 6 6
8 3 4 3
6 8 6 3
Sample Output
3
HINT
1<=K<=N<=M<=250,1<=矩阵元素<=10^9
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 const int maxn=100010; 7 const int maxm=1000010; 8 const int INF=1000000000; 9 int cnt,fir[maxn],to[maxm],nxt[maxm],cap[maxm]; 10 int dis[maxn],gap[maxn],path[maxn],fron[maxn]; 11 queue<int>q; 12 13 struct Net_Flow{ 14 int tot; 15 void Init(int tot_){ 16 memset(dis,0,sizeof(dis)); 17 memset(gap,0,sizeof(gap)); 18 memset(fir,0,sizeof(fir)); 19 cnt=1;tot=tot_; 20 } 21 void add(int a,int b,int c){ 22 nxt[++cnt]=fir[a]; 23 cap[cnt]=c; 24 fir[a]=cnt; 25 to[cnt]=b; 26 } 27 void addedge(int a,int b,int c){ 28 add(a,b,c);add(b,a,0); 29 } 30 bool BFS(int S,int T){ 31 dis[T]=1;q.push(T); 32 while(!q.empty()){ 33 int x=q.front();q.pop(); 34 for(int i=fir[x];i;i=nxt[i]) 35 if(!dis[to[i]]){ 36 dis[to[i]]=dis[x]+1; 37 q.push(to[i]); 38 } 39 } 40 return dis[S]; 41 } 42 int Max_Flow(int S,int T){ 43 if(!BFS(S,T))return 0; 44 for(int i=0;i<tot;i++)fron[i]=fir[i]; 45 for(int i=0;i<tot;i++)gap[dis[i]]+=1; 46 int ret=0,p=S,f,Min; 47 while(dis[S]<=tot){ 48 if(p==T){ 49 f=INF; 50 while(p!=S){ 51 f=min(f,cap[path[p]]); 52 p=to[path[p]^1]; 53 }ret+=f;p=T; 54 while(p!=S){ 55 cap[path[p]]-=f; 56 cap[path[p]^1]+=f; 57 p=to[path[p]^1]; 58 } 59 } 60 61 for(int &i=fron[p];i;i=nxt[i]) 62 if(cap[i]&&dis[to[i]]==dis[p]-1) 63 {path[p=to[i]]=i;break;} 64 65 if(!fron[p]){Min=tot; 66 if(--gap[dis[p]]==0)break; 67 for(int i=fir[p];i;i=nxt[i]) 68 if(cap[i])Min=min(Min,dis[to[i]]); 69 gap[dis[p]=Min+1]+=1;fron[p]=fir[p]; 70 if(p!=S)p=to[path[p]^1]; 71 } 72 } 73 return ret; 74 } 75 }ISAP; 76 int a[260][260]; 77 int n,m,k,S,s1,s2,T; 78 bool Check(int mid){ 79 ISAP.Init(2*n+m+4); 80 ISAP.addedge(S,s1,k); 81 ISAP.addedge(S,s2,n-k); 82 for(int i=1;i<=n;i++){ 83 ISAP.addedge(s1,i,1); 84 ISAP.addedge(s2,n+i,1); 85 for(int j=1;j<=m;j++){ 86 if(i==1) 87 ISAP.addedge(2*n+j,T,1); 88 if(a[i][j]>=mid) 89 ISAP.addedge(i,2*n+j,1); 90 else 91 ISAP.addedge(n+i,2*n+j,1); 92 } 93 } 94 return ISAP.Max_Flow(S,T)==n; 95 } 96 97 int main(){ 98 int l=1,r=0; 99 scanf("%d%d%d",&n,&m,&k); 100 for(int i=1;i<=n;i++) 101 for(int j=1;j<=m;j++){ 102 scanf("%d",&a[i][j]); 103 r=max(r,a[i][j]); 104 } 105 106 T=2*n+m+3; 107 s1=2*n+m+1; 108 s2=2*n+m+2; 109 while(l<=r){ 110 int mid=(l+r)>>1; 111 if(Check(mid))r=mid-1; 112 else l=mid+1; 113 } 114 int ans=INF; 115 for(int i=1;i<=n;i++) 116 for(int j=1;j<=m;j++) 117 if(a[i][j]>=l)ans=min(ans,a[i][j]); 118 printf("%d\n",ans); 119 return 0; 120 }
尽最大的努力,做最好的自己!