简单讲讲上下界网络流

news/2024/10/4 2:31:55

无源汇可行流

无源汇网络流一般不讨论最大流,因为它的流都是环流,分布在各个位置,一是不好统计,二是一般也没有意义。所以一般建图只需要求是否有可行解(但我也没遇到过求输出YES和NO的可行流题目,网上的博客也都只当做有源汇的前置知识讲了)

废话不多说,直接上图。

sxj1.png

第一张图给出了无源汇模型每条边的上下界,绿色数值是每条边的下界值,即至少要流的流量。假设我们先满足下界,如果此时各个点绿色流量的流出和流入值相同,那么直接就是一个可行解,但是显然大部分情况是无法用下界来满足平衡的。我们把每条边上界减去下界的差值当做额外流量,这张图需要流一些额外流量,才能弥补之前的不平衡。

对于下界流出量大于流入量的点,之前其实没有足够的流量供它流出,所以它就需要从前面获得一些额外流量,呈现缺失态(上图点 1 和点 4);对于流入量大于流出量的点,它需要通过出边的额外流量来分掉它的流入量,呈现饱满态(上图点 2,3,5)。那么问题就变成了,能不能找到一条路线,饱满态的起点把流入它的多余流量通过这条路线转移出去,终点获得它之前缺失的流量,中间的点因为流入又流出,所以出入之差不变,这条路线的意义就是平衡了起点和终点。(路线这个概念很重要,是理解整个上下界网络流的关键,它是源汇点任意时的增广路)

我们要弥补所有点的不平衡,就要找到多条路线。具体的,先把原图两点间额外流量设成新图流量,再设置一对虚拟的源汇点,让源点向饱满态的点连一条多余流量(流入量 - 流出量)的边,让缺失态的点向汇点连一条需求流量(流出量-流入量)的边,跑从源点到汇点的最大流,如果最大流等于多余流量(或需求流量)之和,那么就是一组可行解。

初学时有一个疑问就是,饱满态的点流入量已经大于流出量了,为什么还要从源点向他连一条流入边。其实这条虚拟的流入边不是为了增加这个点的流量,而是将所有饱满态的点连在一起,方便同时找到多条增广路,新建的虚拟边流量在原图中是没有任何意义的。

sxj2.png

我们直接来看跑完最大流之后的情况,右图展示了新图流到汇点的两条路径,红色部分是找到了两条路线:2->4->5->1 和 5->1 各自流一个流量,蓝色部分找到了一条路线:3->4 流一个流量。在原图中的体现就是:点 2 通过原图中三条红色边的额外流量,把自己多出来的流量流回了点1 ;点 3 通过原图中蓝色边的额外流量,把自己多出来的流量流给了点 4。至此,原图的所有点流入量和流出量平衡,我们找到了一组可行流。想要输出方案也很简单,新图中每条边的流量是它原图的额外流量,加上下界,就是原图的真实流量。

有源汇上下界可行流

其实我们思考下本质,有源汇与无源汇最大的区别,除了长的样子不同,其实就是我们不再需要平衡源点和汇点的流量,虽然其他点要平衡,但源点可以是一个缺失点,只流出不流入;汇点是一个饱和点,只流入不流出。所以有源汇上下界的一个可行流,需要满足:除源点和汇点以外,其他点流入量等于流出量

我们可以把它改造成无源汇,即从汇点向源点连一条下界为0,上界无穷的新边。不过很多博客讲有源汇上下界时没有具体讲这条边的作用,导致读者到后面理解最大流和最小流时非常困难。

在没有这条边时,我们通过找到的所有增广路,将除源汇点以外的所有点平衡流量,那么这个有源汇上下界模型就是可行的。此时只剩下流出大于流入的源点,流入大于流出的汇点。只要我们把新加的这条边,当做平衡源汇点的一条新路径,那么整张图就相当于无源汇的可行流。那么反过来,如果这张无源汇图我们知道有可行流,那么我们撤销掉新加的无穷大边的流量,原图就会变成一个除源点和汇点以外其他点流量平衡的图,即有源汇上下界可行流。

有源汇上下界最大流(最小流)

直接上图:

sxj3.png

这是一个有源点和汇点的图,虽然看上去有个环,不过我们关注的还是只从源点流到汇点的最大最小流量。

求最大流的前提是,我们需要先让这张图成为可行流:发现点 3 是至少有一个流入量的,所以它一定还要向左流给源点,这一条流量会使得从源点到汇点的总体流量减一,不过没办法,因为这是成为可行流的必要流量。

在我们新建那条汇点到源点的无穷大边,并求解完一个可行流之后,我们冷静下来思考,有源汇最大流的本质是什么,其实就是在其他点流量平衡的前提下,最大化源点的缺失流量(或汇点的饱和流量)。我们还是撤销掉这条无穷大的边,那么这条边的流量,就成为了源点的缺失量,因为这条边本身的意义就是一条弥补源汇点流量差的路线(第一个标题所讲的路线)。

sxj4.png

通过上图的流量,我们找到了一个可行流的解,在这个解中,无穷大的那条边流量是 2,流量平衡的过程改变了原图三条边的剩余流量。此时,如果我们撤销无穷大的边,那么源点的流入流出之差会变成 3,这其实就是一个可行流的流量。

那么聪明的你应该想到了,最大流该如何计算呢,就是在原图中,继续找到一些从源点流到汇点的路线,将源点的缺失量进一步扩大。即:s->1->2->t,流量为 3,此时源点流入流出之差为 6,为有源汇最大流。最小值则相反,找到一些从汇点到源点的路线,即:t->3->s,此时源点缺失量被弥补了一些,流入流出之差变成了 1,为有源汇最小流。


总结求解有源汇上下界最大最小流的步骤:

一、新图跑虚拟源点到虚拟汇点的最大流,判断是否有无源汇可行流。

二、将无穷大那条边的流量返还源汇点,得到有源汇可行流。

三、在原图中继续跑最大流,再加上可行流的流量(无穷大边的流量),得到答案(正着跑得到最大流,倒着跑得到最小流)。

模板:luogu东方文花帖

https://www.luogu.com.cn/problem/P5192

这题就是求个有源汇上下界最大流,很裸的模板,不过要先被传一波教才能读懂题意。

下面的代码中 a 数组存了原图的每一条边,包括上界和下界的信息。然后 solve 函数就是有源汇上下界最大流的全部过程了,包括建边,和上面总结的三个步骤。

#include <bits/stdc++.h>
#define ll long longusing namespace std;
const ll N=501010;
const ll inf=0x3f3f3f3f;inline ll read() {ll sum = 0, f = 1; char c = getchar();while(c<'0' || c>'9') { if(c=='-') f = -1; c = getchar(); }while(c>='0'&&c<='9') { sum = sum * 10 + c - '0'; c = getchar(); }return sum * f;
}ll n,m,s,t,ss,tt;
struct EE{ ll u,v,l,r; } a[N]; ll cnta;
ll du[N];
struct E{ll to,nxt,cap;
}e[N];
ll cnt = 1;
ll head[N],cur[N];
ll dep[N],vis[N];
queue <ll> q;inline void add(ll u,ll v,ll w) {// cout<<u<<" -> "<<v<<" "<<w<<endl;e[++cnt] = (E){ v,head[u],w }; head[u] = cnt;e[++cnt] = (E){ u,head[v],0 }; head[v] = cnt;
}inline bool SPFA(ll S,ll T) {for(ll i=0;i<=tt;i++) dep[i] = inf, vis[i] = 0, cur[i] = head[i];q.push(S); dep[S] = 0;while(!q.empty()) {ll u = q.front(); q.pop();vis[u] = 0;for(ll i=head[u]; i; i=e[i].nxt) {ll v = e[i].to;if(dep[v] > dep[u] + 1 && e[i].cap) {dep[v] = dep[u] + 1;if(vis[v]) continue;q.push(v);vis[v] = 1;}}}return dep[T]!=inf;
}ll DFS(ll u,ll goal,ll flow) {ll res = 0, f;if(u==goal || !flow) return flow;for(ll i=cur[u]; i; i=e[i].nxt) {cur[u] = i;ll v = e[i].to;if(e[i].cap && (dep[v] == dep[u]+1)) {f = DFS(v,goal,min(flow-res,e[i].cap));if(f) {res += f;e[i].cap -= f;e[i^1].cap += f;if(res==flow) break;}}}return res;
}ll solve() {ll ans1 = 0, ans2 = 0, cha = 0;for(ll i=1;i<=cnta;i++) {ll u = a[i].u, v = a[i].v;du[u] += a[i].l;du[v] -= a[i].l;add(u, v, a[i].r-a[i].l);}ll lim = cnt;for(ll u=s;u<=t;u++) {if(du[u]>0) add(u,tt,du[u]), cha += du[u];if(du[u]<0) add(ss,u,-du[u]);}add(t,s,inf);while(SPFA(ss,tt)) cha -= DFS(ss,tt,inf);if(cha) return -1;ans1 = e[cnt].cap;for(ll i=lim+1;i<=cnt;i++) e[i].cap = 0;while(SPFA(s,t)) ans2 += DFS(s,t,inf);return ans1+ans2;
}void chushihua() {cnt = 1;cnta = 0;for(ll i=0;i<=tt;i++) head[i] = du[i] = 0;
}int main() {ll x,y,l,r;while(scanf("%lld%lld",&n,&m)!=EOF) {chushihua();s = 0; t = n+m+1; ss = n+m+2; tt = n+m+3;for(ll i=1;i<=m;i++) {x = read();a[++cnta] = { i+n,t,x,inf };}for(ll i=1;i<=n;i++) {x = read();y = read(); a[++cnta] = { s,i,0,y };while(x--) {y = read()+1; l = read(); r = read();a[++cnta] = { i,y+n,l,r };}}cout<<solve()<<"\n\n";}// n = 3; s = 0, t = 4; ss = 5; tt = 6;// a[++cnta] = {s,1,2,4};// a[++cnta] = {1,2,0,1};// a[++cnta] = {1,3,3,5};// a[++cnta] = {2,t,1,5};// a[++cnta] = {3,t,1,3};// cout<<solve()<<"\n";return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/67540.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Netflix 錯誤 NW-8-18

环境 PS5的奈飞,OpenWrt的树莓派做软路由解决方案 首先重置,如果不行,关机拔掉电源线等待三分钟,重试 Netflix。如果这篇文章对你有用,可以关注本人微信公众号获取更多ヽ(^ω^)ノ ~

Python算法学习

算法学习心得,源码均为Python实现目录绪论数据结构算法算法的特征算法的评价算法的时间复杂度算法的空间复杂度递归汉诺塔问题(递归调用)查找排序二分查找检查排序是否完成冒泡排序选择排序插入排序希尔排序(高级版插入排序)快速排序堆排序(二叉树)python中内置好的堆排…

数学建模学习

数学建模学习,包含各种常用模型和Matlab源码目录 目录目录评价类方法层次分析法搜索引擎算法步骤算法代码F4锁定单元格优劣解距离法算法步骤算法代码自输入权重代码基于熵权法权重的代码灰色关联分析传统数理统计的不足之处该方法的好处算法步骤算法代码基于灰色关联度权重的代…

下载、安装、配置 android-studio-2021.1.1.22-windows

软件安装包:图1 软件安装包提示删除已经存在的版本:图2 提示删除已经存在的版本根据提示选择是:图3 根据提示选择是继续安装:图4图5图6图7图8图9图10

实景三维赋能城镇数字化规划

在数字化浪潮的推动下,城镇规划正经历着前所未有的变革。实景三维技术以其独特的优势,为城镇数字化规划提供了强大的技术支持。今天,我们将深入探讨实景三维技术如何赋能城镇数字化规划。一、城镇规划面临的挑战随着城镇化进程的加快,城镇规划面临着人口增长、资源分配、环…

土地规划中的公共设施布局:科学规划,赋能土地高效利用的艺术

在城市与区域发展的宏大叙事中,公共设施布局如同血管与神经网络,支撑着城市的脉动与感知。合理规划公共设施布局对于提升土地使用效率、促进社会公平、增强居民福祉至关重要。本文将深入探讨如何通过科学方法与创新策略,实现公共设施的高效布局,绘就城市发展的智慧蓝图。一…

js学习1

js实现简单交互 js的外联引入 必须在body里&&你需要交互的元素下方 e.g. <body><div id="box">演示1</div><script src="./演示1.js"></script> </body>实现点击交互 样例1 <!DOCTYPE html> <html l…

动态规划Leetcode96.不同的二叉搜索树

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 解题步骤如下:二叉搜素树的相关概念 寻找规律 思路建立 代码实现1.二叉搜索树的相关概念 ①:若左子树不空,则左子树所有节点的值均小于它的根节点…