Bzoj4443:[Scoi2015]小凸玩矩阵:网络流

来源:互联网 发布:淘宝少女前线初始号 编辑:程序博客网 时间:2024/05/23 18:33

题目链接:4443:[Scoi2015]小凸玩矩阵

二分答案x,判断是否可以去最少n-k+1个数<=x

判断用最大流,行和列都看成点,连边(S,i,1),(i+n,T,1),对于格子(i,j)如果它的数<=x连边(i,j+n,1)

#include<queue>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int maxn=511;const int inf=0x7fffffff/3;int n,m,a[maxn][maxn],tot=1,h[maxn],S,T;struct edge{int to,next,w;}G[maxn*maxn];int cur[maxn],vis[maxn],mx=0,k;void add(int x,int y,int z){G[++tot].to=y;G[tot].next=h[x];h[x]=tot;G[tot].w=z;G[++tot].to=x;G[tot].next=h[y];h[y]=tot;G[tot].w=0;}bool bfs(){for (int i=S;i<=T;++i) vis[i]=-1;queue<int>q; q.push(S); vis[S]=0;while (!q.empty()){int u=q.front(); q.pop();for (int i=h[u];i;i=G[i].next){int v=G[i].to;if (vis[v]==-1&&G[i].w){vis[v]=vis[u]+1;q.push(v);}}}return vis[T]!=-1;}int dfs(int x,int f){if (x==T||f==0) return f;int w,used=0;for (int i=cur[x];i;i=G[i].next)    if (vis[G[i].to]==vis[x]+1){w=f-used;w=dfs(G[i].to,min(w,G[i].w));G[i].w-=w; G[i^1].w+=w;used+=w; if (G[i].w) cur[x]=i;if (used==f) return f;    }if (!used) vis[x]=-1;return used;}int dinic(){int ret=0;while (bfs()){for (int i=S;i<=T;++i) cur[i]=h[i];ret+=dfs(S,inf);}return ret;}bool check(int x){memset(h,0,sizeof(h)); tot=1;for (int i=1;i<=n;++i) add(S,i,1);for (int i=1;i<=m;++i) add(i+n,T,1);for (int i=1;i<=n;++i)    for (int j=1;j<=m;++j)        if (a[i][j]<=x) add(i,j+n,1);int ret=dinic();if (ret>=n-k+1) return 1;else return 0;}int main(){scanf("%d%d%d",&n,&m,&k);S=0; T=n+m+1;for (int i=1;i<=n;++i)    for (int j=1;j<=m;++j)        scanf("%d",&a[i][j]),mx=max(mx,a[i][j]);int l=0,r=mx;while (l<r){int mid=(l+r)>>1;if (check(mid)) r=mid;else l=mid+1;}printf("%d",l);}


4 1
原创粉丝点击