uva11082 Matrix Decompressing (最大流)
2015-08-07 15:41
232 查看
题目链接
此题为一个网络流中最大流的一般用法,题目告诉你n*m矩阵前i行的和,以及前j列的和,限定每个数大小为1到20的大小,叫你输出任意一种满足题意得结果。
其实此题稍微难点的地方就在于那个限制条件,我们可以用一个ans[][]数组记录结果,并预先把每个数大小定为1,这样以后就是从每行的和中减去m,每列的和中减去n,再去建图,因为你已经每个点减去1了,建图时候流量就会相应地减少才对。现在是建图,建图很简单,我们只需要先把行和列编号,把行编号为1~n,那么列编号为1+n~m+n,再把点编号,因为有n*m个点,而且前面行和列已经用去n+m个点,所以在编号时从1+n+m~n*m+n+m即可。然后行从源点向每行建边,流量为此行剩余的总和,行向其对应的点建边,流量19(因为每个点上限为20,已经给了1,剩余19),列建边同理,每个点向对应的列连一条边,流量为19,列向汇点连一条边,流量为该列剩余的流量,代码如下:
此题为一个网络流中最大流的一般用法,题目告诉你n*m矩阵前i行的和,以及前j列的和,限定每个数大小为1到20的大小,叫你输出任意一种满足题意得结果。
其实此题稍微难点的地方就在于那个限制条件,我们可以用一个ans[][]数组记录结果,并预先把每个数大小定为1,这样以后就是从每行的和中减去m,每列的和中减去n,再去建图,因为你已经每个点减去1了,建图时候流量就会相应地减少才对。现在是建图,建图很简单,我们只需要先把行和列编号,把行编号为1~n,那么列编号为1+n~m+n,再把点编号,因为有n*m个点,而且前面行和列已经用去n+m个点,所以在编号时从1+n+m~n*m+n+m即可。然后行从源点向每行建边,流量为此行剩余的总和,行向其对应的点建边,流量19(因为每个点上限为20,已经给了1,剩余19),列建边同理,每个点向对应的列连一条边,流量为19,列向汇点连一条边,流量为该列剩余的流量,代码如下:
#include<stdio.h> #include<string.h> #include<vector> #include<queue> #include<algorithm> #define maxn 2010 #define inf 0x7fffffff using namespace std; struct edge { int from,to,cap,flow; }; vector<edge> edges; vector<int> G[maxn]; int d[maxn],cur[maxn],ans[22][22]; int numx[22],numy[22],id[22][22]; bool vis[maxn]; int s,t,n,m,T; void add(int from,int to,int cap) { edges.push_back((edge){from,to,cap,0}); edges.push_back((edge){to,from,0,0}); int m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool bfs() { memset(vis,false,sizeof(vis)); memset(d,0,sizeof(d)); queue<int> q; q.push(s); d[s]=0,vis[s]=true; while(!q.empty()) { int x=q.front(); q.pop(); for(int i=0;i<G[x].size();i++) { edge& e=edges[G[x][i]]; if(!vis[e.to]&&e.cap>e.flow) { vis[e.to]=true; d[e.to]=d[x]+1; q.push(e.to); } } } return vis[t]; } int dfs(int x,int a) { if(x==t||a==0) return a; int flow=0,f; for(int& i=cur[x];i<G[x].size();i++) { edge& e=edges[G[x][i]]; if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0) { e.flow+=f; edges[G[x][i]^1].flow-=f; flow+=f; a-=f; if(a==0) break; } } return flow; } void maxflow() { int flow=0; while(bfs()) { memset(cur,0,sizeof(cur)); flow+=dfs(s,inf); } for(int i=1;i<=n;i++) { for(int j=1;j<G[i].size();j++) { int tem=edges[G[i][j]].to-n*m; int idy=tem%m==0?m:tem%m; ans[i][idy]+=edges[G[i][j]].flow; } } } int main() { scanf("%d",&T); for(int ca=1;ca<=T;ca++) { scanf("%d%d",&n,&m); for(int i=0;i<maxn;i++) G[i].clear(); int k=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ans[i][j]=1,id[i][j]=++k; edges.clear(); s=0,t=4*n*m; for(int i=1;i<=n;i++) scanf("%d",&numx[i]); for(int j=1;j<=m;j++) scanf("%d",&numy[j]); for(int i=n;i>=2;i--) numx[i]-=numx[i-1]; for(int j=m;j>=2;j--) numy[j]-=numy[j-1]; for(int i=1;i<=n;i++) { add(s,i,numx[i]-m); for(int j=1;j<=m;j++) { add(i,id[i][j]+n*m,19); } } for(int j=1;j<=m;j++) { add(j+2*n*m,t,numy[j]-n); for(int i=1;i<=n;i++) { add(id[i][j]+n*m,j+2*n*m,19); } } maxflow(); printf("Matrix %d\n",ca); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) if(j<m) printf("%d ",ans[i][j]); else printf("%d\n",ans[i][j]); } //printf("\n"); } return 0; }
相关文章推荐
- ios网络请求 get——post 区别
- 彻底解决android中Textview控件文本自动换行问题
- 用IoAllocateIrp创建IRP
- poj 2406 Power Strings
- body的margin问题。
- hdu 5362 Just A String 2015多校联合训练赛#6 动态规划
- jQuery.extend 函数详解
- jQuery实现信息提示框(带有圆角框与动画)效果
- Mac版的Android Eclipse识别安卓真机
- ApkTool在Mac上的安装和使用
- SlickEdit 的安装与配置
- Object源码研究2——getClass()方法分析
- HDOJ 2020 绝对值排序 (水)
- WSGI详解汇总
- UIView添加动画
- 创业者靠什么成功?
- IOS第八天(1:UITableViewController团购,数据转模型,xib显示数据)
- Oracle学习之DATAGUARD(五) 创建logic standby
- java 代码中如何预防空指针异常
- 说说SAP Business One怎么样