P4251 [SCOI2015]小凸玩矩阵
作者:互联网
P4251 [SCOI2015]小凸玩矩阵
比较有思维含量的二分图
大概一眼看出二分
对于一个mid,我们先把每一个value小于mid的数字导出来
其实选一个数字在二分图中就是将行和列匹配起来
那么就很好办了,check一个mid和不合法,我们只要二分图最大匹配一下,答案如果>=min(n,m)-k+1即可
代码:
#include<bits/stdc++.h> using namespace std; #define re register #define il inline struct node{ int x,y; int val; }; const int N=305; const int M=500005; int n,m,k; int s[N][N]; int l=1,r,ans; node a[N*N+100]; int c[N][N]; int sx[N],sy[N],us[N]; il bool cmp(node x,node y){ return x.val<y.val; } il bool work(int u){ //cout<<u<<endl; for(re int v=1;v<=m;v++){ if(c[u][v]&&!us[v]){ us[v]=1; if(sy[v]==-1||work(sy[v])){ sx[u]=v; sy[v]=u; return 1; } } } return 0; } il int check(int x){ int sum=0; memset(c,0,sizeof(c)); memset(sx,-1,sizeof(sx)); memset(sy,-1,sizeof(sy)); for(re int i=1;i<=n;i++){ for(re int j=1;j<=m;j++){ if(s[i][j]>x) continue; c[i][j]=1; } } for(int i=1;i<=n;i++){ memset(us,0,sizeof(us)); sum+=work(i); } return sum; } int main(){ scanf("%d%d%d",&n,&m,&k); for(re int i=1;i<=n;i++){ for(re int j=1;j<=m;j++){ scanf("%d",&s[i][j]); a[(i-1)*m+j].val=s[i][j]; a[(i-1)*m+j].x=i; a[(i-1)*m+j].y=j; } } sort(a+1,a+n*m+1,cmp); r=1e9; /* for(re int i=1;i<=n*m;i++){ printf("%d ",a[i]); } printf("\n"); */ while(l<=r){ //cout<<l<<" "<<r<<endl; int mid=(l+r)>>1; if(check(mid)>=n-k+1) ans=mid,r=mid-1; else l=mid+1; } printf("%d\n",ans); return 0; }
标签:node,二分,const,int,ans,mid,小凸,P4251,SCOI2015 来源: https://www.cnblogs.com/QYJ060604/p/11519336.html