bzoj 2406: 矩阵 上下界网络流判定
2406: 矩阵
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 138 Solved: 46
[Submit][Status][Discuss]
Description
Input
第一行两个数n、m,表示矩阵的大小。
接下来n行,每行m列,描述矩阵A。
最后一行两个数L,R。
Output
第一行,输出最小的答案;
Sample Input
2 2
0 1
2 1
0 1
0 1
2 1
0 1
Sample Output
1
HINT
对于100%的数据满足N,M<=200,0<=L<=R<=1000,0<=Aij<=1000
看网上没什么题解,就随便写一写吧,二分答案转化为判定问题:构造矩阵,使得每行每列之和分别满足在一个区间内,这就是很裸很裸的带下界网络流判定问题。直接行列分别建点即可,然而我写的时候数组开小了,wa了一个上午。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 220 #define MAXV MAXN*MAXN #define MAXE MAXV*2 #define INF 0x3f3f3f3f #define BIG 100000000 #define abs(x) ((x)<0?(-(x)):(x)) struct Edge { int val,np; Edge *next,*neg; }E[MAXE],*V[MAXV]; int tope=1; int sour=0,sink=1; inline void addedge(int x,int y,int z) { // cout<<"Add edge:<"<<tope+1<<">"<<x<<" "<<y<<":"<<z<<endl; E[++tope].np=y; E[tope].val=z; E[tope].next=V[x]; V[x]=&E[tope]; E[++tope].np=x; E[tope].val=0; E[tope].next=V[y]; V[y]=&E[tope]; E[tope].neg=&E[tope-1]; E[tope-1].neg=&E[tope]; } int q[MAXV],lev[MAXV]; int vis[MAXV],bfstime=0; bool bfs() { int head=-1,tail=0; Edge *ne; lev[sour]=1; vis[sour]=++bfstime; q[0]=sour; while (head<tail) { for (ne=V[q[++head]];ne;ne=ne->next) { if (!ne->val || vis[ne->np]==bfstime)continue; q[++tail]=ne->np; vis[ne->np]=bfstime; lev[ne->np]=lev[q[head]]+1; } } return vis[sink]==bfstime; } int dfs(int now,int maxf) { int ret=0,t; if (now==sink || !maxf)return maxf; Edge* ne; for (ne=V[now];ne;ne=ne->next) { if (!ne->val || lev[ne->np]!=lev[now]+1)continue; t=dfs(ne->np,min(maxf,ne->val)); ne->val-=t; ne->neg->val+=t; maxf-=t; ret+=t; //cout<<"Flow:"<<now<<"-"<<ne->np<<":"<<x<<"("<<ne->val<<")"<<endl; } if (!ret)lev[now]=-1; return ret; } int dinic() { int ret=0; while (bfs()) { ret+=dfs(sour,INF); } return ret; } int mat[MAXN][MAXN]; int degin[MAXV],degout[MAXV]; int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); int n,m,a,b; scanf("%d%d",&n,&m); for (int i=0;i<n;i++) for (int j=0;j<m;j++) { scanf("%d",&mat[i][j]); } scanf("%d%d",&a,&b); int l=-1,r=100010; int tsour=2,tsink=3; while (l+1<r) { memset(degin,0,sizeof(degin)); memset(degout,0,sizeof(degout)); memset(V,0,sizeof(V)); tope=-1; int mid=(l+r)>>1; for (int i=0;i<n;i++) { int s=0; for (int j=0;j<m;j++) s+=mat[i][j]; degout[tsour]+=s-mid; degin[4+i]+=s-mid; addedge(tsour,4+i,mid*2); } for (int i=0;i<m;i++) { int s=0; for (int j=0;j<n;j++) s+=mat[j][i]; degin[tsink]+=s-mid; degout[4+i+n]+=s-mid; addedge(4+i+n,tsink,mid*2); } for (int i=0;i<n;i++) { for (int j=0;j<m;j++) { degout[4+i]+=a; degin[4+j+n]+=a; addedge(4+i,4+j+n,b-a); } } addedge(tsink,tsour,BIG); int sum=0; for (int i=2;i<4+n+m;i++) { if (degout[i]>degin[i]) { sum+=degout[i]-degin[i]; addedge(i,sink,degout[i]-degin[i]); } else if (degin[i]>degout[i]) addedge(sour,i,degin[i]-degout[i]); } if (dinic()==sum) r=mid; else l=mid; } printf("%d\n",r); }
by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载
本博客已停用,新博客地址:http://mhy12345.xyz