bzoj3698
来源:互联网 发布:淘宝网女士夏季服装 编辑:程序博客网 时间:2024/06/05 11:17
这道题网上题解到处都是,在此就不赘述了。
看到这题时,我一开始的想法是对于每个点i!=n && j!=n
),向其所在行和列连边。
但这样是有问题的,因为可能行和列所连的边流量不同,这显然是不对的。
感觉网络流题目查错一般适合静态差错,因为网络流模板一般不太会打错,bug大多出在见图上,单步跟踪很难发现。
下面就是比q234rty大爷慢到不知道哪里去的代码。
upd:刚才突然发现自己不理解自己的做法了。
事实上,对于有源有汇有上下界的最大流,我在此的做法是先加附加源汇,跑一遍有源有汇有上下界的可行流,再在残量网络上跑最大流。本来答案应该是新增的流量加原始边的流量下界之和,但注意到t->s有一条(0,inf)的边,第一遍跑完后会产生流量为原始边的流量下界之和的反向边,然后第二遍时会把这条边的流量自动加上,就不必手动累加了。
#include <cstdio>const int N=310,M=100010,inf=1<<30;struct graph{ struct edge{ int to,next,flow; edge(int _to=0,int _next=0,int _flow=0):to(_to),next(_next),flow(_flow){} }e[M<<1]; int h[N],d[N],q[N],t,w,xb,n,cur[N],T; void addedge(int x,int y,int z){ e[++xb]=edge(y,h[x],z); h[x]=xb; e[++xb]=edge(x,h[y],0); h[y]=xb; } inline int o(int x){ if(x&1)return x+1; else return x-1; } bool bfs(int x,int y){ for(int i=1;i<=n;++i)d[i]=cur[i]=0;d[x]=1;t=0;w=1;q[1]=x; while(t<w){ int u=q[++t]; for(int i=h[u];i;i=e[i].next) if(e[i].flow && !d[e[i].to]){ d[e[i].to] =d[u]+1; q[++w]=e[i].to; if(e[i].to==T)return 1; } } return d[y]; } inline int min(int x,int y){ return x<y?x:y; } int dfs(int x,int f){ if(x==T || !f)return f;int flow=0; for(int&i=cur[x];i;i=e[i].next)if(e[i].flow && d[e[i].to]==d[x]+1){ int a=dfs(e[i].to,min(f,e[i].flow)); if(a){ e[i].flow-=a;e[o(i)].flow+=a;flow+=a;f-=a; if(!f)break; } } return flow; } int maxflow(int x,int y){ T=y; int ans=0; while(bfs(x,y)){ for(int i=1;i<=n;++i)cur[i]=h[i]; ans+=dfs(x,1<<30); } return ans; }}g;int n,i,u[M],v[M],l[M],r[M],x,z,xb,j,k=1,out[M],s;double y;int main(){ scanf("%d",&n); u[xb=1]=n<<1,v[1]=1,l[1]=0,r[xb]=inf; for(i=1;i<=n;++i) for(j=1;j<=n;++j){ scanf("%lf",&y);x=y;if(y<0 && x!=y)--x;z=x+(x!=y); if(i==n && j==n)continue;l[++xb]=x,r[xb]=z; if(j==n)u[xb]=1,v[xb]=i+1; else if(i==n)u[xb]=j+n,v[xb]=n<<1; else u[xb]=i+1,v[xb]=j+n; } for(i=1;i<=xb;++i)out[u[i]]+=l[i],out[v[i]]-=l[i]; for(i=1;i<=n<<1;++i) if(out[i]>0)g.addedge(i,n*2+2,out[i]),s+=out[i]; else if(out[i])g.addedge(n<<1|1,i,-out[i]); for(i=1;i<=xb;++i)if(l[i]<r[i])g.addedge(u[i],v[i],r[i]-l[i]); g.n=n*2+2; if(g.maxflow(n<<1|1,n*2+2)<s)return puts("No"),0; printf("%d\n",g.maxflow(1,n<<1)*3); return 0;}
阅读全文
0 0
- bzoj3698
- bzoj3698 XWW的难题
- 带上下界网络流小练(Bzoj2502&&Bzoj2055&&Bzoj3698)
- 【bzoj3698】XWW的难题 有上下界的网络流
- 【bzoj3698】【XWW的难题】【有上下界的网络流】
- bzoj3698 XWW的难题(有源汇有上下界最大流)
- [BZOJ3698]XWW的难题(有源汇有上下界的最大流)
- [bzoj3698]XWW的难题 有源汇的上下界最大流
- bzoj3698: XWW的难题 //有上下界有源汇最大流
- ReactNative基础(一)编写一个登录页面
- 鏖战字符串
- c# 操作Access数据库
- iOS 获取手机型号信息大全
- SQL查询的艺术学习笔记--数据的完整性
- bzoj3698
- JAVA 并发类(五) CopyOnWriteArraySet 源码分析
- QQ点击分享
- 自定义实现简单的ios风格的弹窗加载进度框,一步步走向封装
- Java面向对象复习笔记
- 具有NestedScrollView并且内嵌套RecyclerView,打开页面时不显示在顶部的解决方法
- c语言,空指针,野指针,通用指针
- SQL查询的艺术学习笔记--数据的更新和删除
- 微信公众号 网页授权开发