博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
网络流 - 上下界网络流
阅读量:5278 次
发布时间:2019-06-14

本文共 3670 字,大约阅读时间需要 12 分钟。

本文为博主原创文章,转载请标明出处。

原文链接

 

本文概述

  1. 问题模型

  2. 前言

  3. 无源汇可行流

  4. 有源汇可行流

  5. 有源汇最大流

  6. 有源汇最小流

  7. 模板题链接

  8. 模板

  9. 鸣谢

 

问题模型

   $n$ 个点 , $m$ 条边。每一条边有流量下界和上界,定义边 $(x,y,L,U)$ 表示一条从 $x$ 到 $y$ 的边,流量的下界和上界分别为 $L$ 和 $U$ ,求……

 

前言

  解决这类网络流问题的本质就是通过特殊构图将上下界网络流问题变成普通的最大流问题。由于这几种构造的正确性都很容易感性理解,所以这里证明了。

 

无源汇可行流

问题

  求一个使得所有边的满足上下界限制且每一个点的流量都平衡的方案。

构造方案

  定义 “边 $(x,y,cap)$" 表示一条从 $x$ 到 $y$ 且容量为 $cap$ 的边。

  首先,对于每一条边 $(x,y,L,U)$ ,我们在图中建边 $(x,y,U-L)$ 。

  这样显然已经导致了途中流量的不平衡,记点 $x$ 当前入流量与出流量之差为 $in[x]$ 。我们新建超级源 $S$ 和超级汇 $T$ ,对于当前点 $i$,如果流量不平衡,那么我们分两种情况讨论:

  1. 入度大于出度,即 $in[i]>0$ ,那么我们在图中建立边 $(S,i,in[i])$ ,如下图中的点 $a$ 。

  2. 入度小于出度,即 $in[i]<0$ ,那么我们在图中建立边 $(i,T,-in[i])$ ,如下图中的点 $b$ 。

      

  然后就只需要跑一次 $S$ 到 $T$ 的最大流,就可以得到可行流了。具体地,一条边的流量大小为 它的流量下界值 加上 跑完最大流后当前边的流量值

 

有源汇可行流

问题

  给定源点 $s$ 和汇点 $t$ ,不要求这两个点满足流量平衡,但是其他点都要满足,求可行流。

构造方案

  这类问题的构造方案就是在无源汇可行流的基础上,添加一条边 $(t,s,\infty)$ 即可。

 

有源汇最大流

问题

  在有源汇可行流的基础上,求源点 $s$ 到汇点 $t$ 的最大流。

构造方案

  首先我们跑出有源汇可行流。

  记录当前流量。

  删除边 $(t,s,\infty)$ ,在残量网络上求 $s$ 至 $t$ 的最大流,新增的流加上原有的流 即答案。

  这里有一个小 trick : 不删除边 $(t,s,\infty)$ ,直接在残余网络上求出 $s$ 至 $t$ 的最大流即答案。为什么这样是对的?考虑在求可行流的之后,边 $(t,s,\infty)$ 的反向边的流量就是可行流大小。在求最大流的时候,我们可以把答案看成两部分:一部分是把 $(t,s,\infty)$ 的反向边流量退回去所得到的流量,一部分是原图残余网络的最大增广流量。于是,我们得到的就是这两部分的和。这样做显然省去了一些操作。

 

有源汇最小流

问题

  在有源汇可行流的基础上,求源点 $s$ 到汇点 $t$ 的最大流。

构造方案

  首先我们跑出有源汇可行流。

  记录当前流量。

  删除边 $(t,s,\infty)$ ,在残余网络上求 $t$ 至 $s$ 的最大流,原有的流量减去这次算出来的流量 即答案。

  这个可以理解成通过最大化退流量来使得流量最小。

 

模板题链接

  LOJ dafa好。

  

  

  

 

模板

#include 
using namespace std;typedef long long LL;struct Edge{ int x,y,nxt; LL cap; Edge(){} Edge(int a,int b,LL c,int d){ x=a,y=b,cap=c,nxt=d; }};struct Network{ static const int N=50010,M=175010*2; static const LL INF=1LL<<50; Edge e[M],tmp[M]; int n,S,T,fst[N],cur[N],cnt; int q[N],head,tail; int begin[N],end[N],vis[M]; LL MaxFlow,dis[N]; void clear(int _n){ n=_n,cnt=1; memset(fst,0,sizeof fst); } void add(int a,int b,LL c){ e[++cnt]=Edge(a,b,c,fst[a]),fst[a]=cnt; e[++cnt]=Edge(b,a,0,fst[b]),fst[b]=cnt; } void rebuild(){ memset(vis,0,sizeof vis); end[0]=1; for (int i=1;i<=n;i++){ begin[i]=(end[i]=end[i-1])+1; for (int j=fst[i];j;j=e[j].nxt){ tmp[vis[j]=++end[i]]=e[j]; if (vis[j^1]){ tmp[vis[j]].nxt=vis[j^1]; tmp[vis[j^1]].nxt=vis[j]; } } } swap(e,tmp); } void init(){ for (int i=1;i<=n;i++) cur[i]=begin[i]; } void init(int _S,int _T){ S=_S,T=_T,MaxFlow=0,init(); } int bfs(){ memset(dis,0,sizeof dis); head=tail=0; q[++tail]=T,dis[T]=1; while (head
0) g.add(S,i,in[i]),Sum+=in[i]; else if (in[i]<0) g.add(i,T,-in[i]); } bool CanFlow(){ build(); g.rebuild(); return g.Auto(S,T)>=Sum; } int cur; int GetTS(){ for (int i=2;i<=g.cnt;i++) if (g.e[g.e[i].nxt].cap==(INF>>1)) return i; return -1; } bool CanFlow(int s,int t){ build(); g.add(t,s,INF>>1); g.rebuild(); cur=GetTS(); LL v=g.Auto(S,T); return v>=Sum; } LL MaxFlow(int s,int t){ if (!CanFlow(s,t)) return -1; return g.Auto(s,t); } LL MinFlow(int s,int t){ if (!CanFlow(s,t)) return -1; LL now=g.e[cur].cap; g.e[cur].cap=g.e[g.e[cur].nxt].cap=0; return now-g.Auto(t,s); }}g;int read(){ int x=0; char ch=getchar(); while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x;}int n,m,S,T;signed main(){ n=read(),m=read(),S=read(),T=read(); g.clear(n); for (int i=1;i<=m;i++){ int x=read(),y=read(),L=read(),U=read(); g.add(x,y,L,U); } LL ans=g.MinFlow(S,T); if (!~ans) puts("please go home to sleep"); else printf("%lld",ans); return 0;}

  

 

鸣谢

  感谢 LOJ ,提供模板题链接。

  谢谢 LOJ117 运行效率榜第一的 wxh 代码供学习。

  wzzlh!告诉了我那个 trick 正确的原因。我好菜啊 /kel /kel /kel。

 

转载于:https://www.cnblogs.com/zhouzhendong/p/LU-NetWork-Flows.html

你可能感兴趣的文章
生成随机数的模板
查看>>
Mysql 数据库操作
查看>>
转:linux终端常用快捷键
查看>>
UVa 11059 最大乘积
查看>>
数组分割问题求两个子数组的和差值的小
查看>>
composer 报 zlib_decode(): data error
查看>>
hdu 3938 并查集
查看>>
《深入分析Java Web技术内幕》读书笔记之JVM内存管理
查看>>
python之GIL release (I/O open(file) socket time.sleep)
查看>>
软件开发与模型
查看>>
161017、SQL必备知识点
查看>>
kill新号专题
查看>>
MVC学习系列——Model验证扩展
查看>>
字符串
查看>>
vue2.x directive - 限制input只能输入正整数
查看>>
实现MyLinkedList类深入理解LinkedList
查看>>
自定义返回模型
查看>>
C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 客户端多网络支持
查看>>
HDU 4122
查看>>
Suite3.4.7和Keil u3自带fx2.h、fx2regs.h文件的异同
查看>>