bzoj 2406: 矩阵 二分答案+上下界网络流
2017-07-15 14:37
465 查看
题意
N,M<=200,0<=L<=R<=1000,0<=Aij<=1000
分析
这题一看就觉得是网络流模型。。。问题在于如何建图。首先我们二分答案,将其转化为判定性问题。
设矩阵A的第i行元素和为r[i],第j列元素和为c[j],若想满足当前答案,那么B的第i行的总和范围在[r[i]-mid,mid+r[i]],列同理。我们把每行看做一个点,每列看做一个点,构建二分图。原点向每个行点连边,上下界为[r[i]-mid,mid+r[i]],列点向汇点连边,上下界为[c[i]-mid,mid+c[i]]。行点列点之间两两连边,上下界为[L,R]。那么问题就转换成了是否存在可行流。只要跑一遍上下界网络流就好了。
若想构造方案那也很简单,跑一遍网络流后,Bi,j就等于第i行和第j列之间连的边的流量。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=505; const int inf=0x3f3f3f3f; int n,m,cnt,s,t,S,T,last ,dis ,cur ,d ,r ,c ,L,R,num ; struct edge{int to,next,c;}e[N*N*2]; queue<int> que; int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void addedge(int u,int v,int c) { e[++cnt].to=v;e[cnt].c=c;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].c=0;e[cnt].next=last[v];last[v]=cnt; } bool bfs() { for (int i=s;i<=T;i++) dis[i]=0; while (!que.empty()) que.pop(); dis[S]=1;que.push(S); while (!que.empty()) { int u=que.front();que.pop(); for (int i=last[u];i;i=e[i].next) if (e[i].c&&!dis[e[i].to]) { dis[e[i].to]=dis[u]+1; if (e[i].to==T) return 1; que.push(e[i].to); } } return 0; } int dfs(int x,int maxf) { if (x==T||!maxf) return maxf; int ret=0; for (int &i=cur[x];i;i=e[i].next) if (e[i].c&&dis[e[i].to]==dis[x]+1) { int f=dfs(e[i].to,min(e[i].c,maxf-ret)); e[i].c-=f; e[i^1].c+=f; ret+=f; if (maxf==ret) break; } return ret; } int dinic() { int ans=0; while (bfs()) { for (int i=0;i<=T;i++) cur[i]=last[i]; ans+=dfs(S,inf); } return ans; } void clear() { cnt=1; memset(last,0,sizeof(last)); memset(d,0,sizeof(d)); s=0;t=n+m+1;S=n+m+2;T=n+m+3; } bool check(int mid) { clear(); addedge(t,s,inf); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) addedge(i,j+n,R-L),d[i]-=L,d[j+n]+=L,num[i][j]=cnt; for (int i=1;i<=n;i++) { int p=max(0,r[i]-mid),q=mid+r[i]; addedge(s,i,q-p);d[s]-=p;d[i]+=p; } for (int i=1;i<=m;i++) { int l=max(0,c[i]-mid),r=mid+c[i]; addedge(i+n,t,r-l);d[i+n]-=l;d[t]+=l; } int tot=0; for (int i=s;i<=t;i++) if (d[i]>0) addedge(S,i,d[i]),tot+=d[i]; else if (d[i]<0) addedge(i,T,-d[i]); return dinic()==tot; } int main() { n=read();m=read(); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { int x=read(); r[i]+=x;c[j]+=x; } L=read();R=read(); int l=0,r=200000; while (l<=r) { int mid=(l+r)/2; if (check(mid)) r=mid-1; else l=mid+1; } printf("%d\n",r+1); return 0; }
相关文章推荐
- BZOJ 2406: 矩阵 [上下界网络流 二分答案]
- [BZOJ2406]矩阵(二分+有上下界的网络流)
- [二分 & 上下界网络流] BZOJ2406. 矩阵
- bzoj2406 矩阵 二分+有源汇上下界网络流
- 【BZOJ2406】矩阵 二分+有上下界的可行流
- bzoj 2406: 矩阵 上下界网络流判定
- [上下界网络流] BZOJ2406: 矩阵
- [BZOJ2406]矩阵(二分+有源汇有上下界的可行流)
- BZOJ 2406 二分+有上下界的网络流判定
- bzoj 2406 二分+有源有汇上下界网络流可行流判定
- [BZOJ2406]矩阵(二分+有源汇有上下界的可行流)
- bzoj 4443: [Scoi2015]小凸玩矩阵 二分答案+网络流
- 【bzoj2406】矩阵 二分+有上下界可行流
- [上下界网络流判定] BZOJ 2406 矩阵
- 【二分+上下界网络流】BZOJ2406 矩阵
- bzoj 2406: 矩阵 (有上下界的网络流)
- BZOJ 1189: [HNOI2007]紧急疏散evacuate|网络流|二分答案
- 【矩阵哈希】【二分答案】【哈希表】bzoj1567 [JSOI2008]Blue Mary的战役地图
- [上下界网络流 二分] BZOJ 3698 XWW的难题
- BZOJ 3993 [SDOI 2015] 网络流+二分答案 解题报告