【模板】最大流之上下界可行流

ACM模板


目录

      • 无源汇上下界可行流
      • 有源汇上下界最大流
      • 有源汇上下界最小流

无源汇上下界可行流

问题: 给定一个网络,求一个流满足:每条边的流量处在给定的下界和上届[lower,upper]之间,满足流量守恒

首先我们在原网络中确定一个全部是下界的流网络,当然此流不一定是可行流因为其不一定满足流量守恒,不妨叫此流流①
此时问题转化成找到一个流②,每条边的流量处在[0,upper-lower]之间,此流与之前的流①相加(流①+流②)满足流量守恒,是一个可行流。显然流②不一定是可行流,但是我们可以经过以下调整将其变成一个可行流,从而能过求出流②

  • A(u)=∑toi=uf(i)−∑fromi=uf(i)A(u)=\sum_{toi=u}f(i)-\sum_{fromi=u}f(i)A(u)=toi=uf(i)fromi=uf(i)即流入减去流出
  • A(u)>0A(u)>0A(u)>0,源点SSSuuu点连边,容量是A(u)A(u)A(u)
  • A(u)<0A(u)<0A(u)<0uuu点向汇点TTT连边,容量是−A(u)-A(u)A(u)

如果满流此时即可求出流②(否则无解),再加上流①即是满足题意的可行流
无源汇上下界可行流

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=210,M=(10310+N)*2;
int n,m,S,T;
int h[N],e[M],ne[M],l[M],f[M],idx;
int d[N],q[N],A[N],cur[N];
void add(int a,int b,int c,int d)// 下界c 上届d
{                                        //建图上界-下界e[idx]=b,ne[idx]=h[a],l[idx]=c,f[idx]=d-c,h[a]=idx++;e[idx]=a,ne[idx]=h[b],f[idx]=0,h[b]=idx++;
}
bool bfs()
{memset(d,-1,sizeof d);int tt=0,hh=0;d[S]=0,q[0]=S,cur[S]=h[S];while(hh<=tt){int t=q[hh++];for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(d[j]==-1&&f[i]){d[j]=d[t]+1;cur[j]=h[j];if(j==T) return 1;q[++tt]=j;}}}return 0;
}
int dfs(int u=S,int flow=0x3f3f3f3f)
{if(u==T) return flow;int rmn=flow;for(int i=cur[u];i!=-1&&rmn;i=ne[i]){cur[u]=i;int j=e[i];if(d[j]==d[u]+1&&f[i]){int t=dfs(j,min(f[i],rmn));if(!t) d[j]=-1;f[i]-=t,f[i^1]+=t,rmn-=t;}}return flow-rmn;
}
int dinic()
{int r=0;while(bfs()) r+=dfs();return r;
}
int main()
{cin>>n>>m;S=0,T=n+1;memset(h,-1,sizeof h);for(int i=1;i<=m;i++){int a,b,c,d;cin>>a>>b>>c>>d;add(a,b,c,d);A[b]+=c,A[a]-=c;}int tot=0;for(int i=1;i<=n;i++){if(A[i]>0) add(S,i,0,A[i]),tot+=A[i];else if(A[i]<0)add(i,T,0,-A[i]);}if(tot!=dinic())cout<<"NO\n";else{cout<<"YES\n";for(int i=0;i<2*m;i+=2)cout<<f[i^1]+l[i]<<'\n';// 流②+流①}return 0;
}

有源汇上下界最大流

连接一条t->s下界是0上界是∞∞的边,由此转化循环流问题(无源汇上下界可行流)

按照循环流问题建图,首先跑dinic看是否能够找到一条可行流(即判断是否是满流)
然后在换源点和汇点并删去t->s的边再跑一边dinic(榨干残留网络),可行流+第二次dinic即是最大流

心里没有一点AC数的详细证明

有源汇上下界最大流

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=210,M=(N+10000)*2;
int h[N],e[M],ne[M],f[M],idx;
int n,m,S,T;
int d[N],q[N],cur[N],A[N];
void add(int a,int b,int c)
{e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
bool bfs()
{int tt=0,hh=0;memset(d,-1,sizeof d);d[S]=0,cur[S]=h[S],q[0]=S;while(hh<=tt){int t=q[hh++];for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(d[j]==-1&&f[i]){d[j]=d[t]+1;cur[j]=h[j];if(j==T) return 1;q[++tt]=j;}}}return 0;
}
int dfs(int u=S,int flow=0x3f3f3f3f)
{if(u==T) return flow;int rmn=flow;for(int i=cur[u];i!=-1&&rmn;i=ne[i]){cur[u]=i;int j=e[i];if(d[j]==d[u]+1&&f[i]){int t=dfs(j,min(f[i],rmn));if(!t) d[j]=-1;f[i]-=t,f[i^1]+=t,rmn-=t;}}return flow-rmn;
}int dinic()
{int r=0;while(bfs()) r+=dfs();return r;
}
int main()
{int s,t;cin>>n>>m>>s>>t;memset(h,-1,sizeof h);S=0,T=n+1;for(int i=1;i<=m;i++){int a,b,c,d;cin>>a>>b>>c>>d;add(a,b,d-c);A[a]-=c,A[b]+=c;}int tot=0;for(int i=1;i<=n;i++){if(A[i]>0)add(S,i,A[i]),tot+=A[i];else if(A[i]<0)add(i,T,-A[i]);}add(t,s,0x3f3f3f3f);if(dinic()!=tot) cout<<"No Solution\n";else{int f1=f[idx-1];S=s,T=t;f[idx-1]=f[idx-2]=0; //删去 t->s的边cout<<f1+dinic()<<'\n';}
}

有源汇上下界最小流

最小流=可行流+++s->t流
由于可行流固定,为了使结果最小即s->t流最小
由于 s->t的流= - t->s的流
如果t->s求最大流,那么s->t就是最小流,fs→t=−ft→sf_{s\to t}=-f_{t\to s}fst=fts 这也是为什么相减的原因

有源汇上下界最小流

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=50010,M=(N+126000)*2;
int h[N],e[M],ne[M],f[M],idx;
int n,m,S,T;
int d[N],q[N],cur[N],A[N];
void add(int a,int b,int c)
{e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
bool bfs()
{int tt=0,hh=0;memset(d,-1,sizeof d);d[S]=0,cur[S]=h[S],q[0]=S;while(hh<=tt){int t=q[hh++];for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(d[j]==-1&&f[i]){d[j]=d[t]+1;cur[j]=h[j];if(j==T) return 1;q[++tt]=j;}}}return 0;
}
int dfs(int u=S,int flow=0x3f3f3f3f)
{if(u==T) return flow;int rmn=flow;for(int i=cur[u];i!=-1&&rmn;i=ne[i]){cur[u]=i;int j=e[i];if(d[j]==d[u]+1&&f[i]){int t=dfs(j,min(f[i],rmn));if(!t) d[j]=-1;f[i]-=t,f[i^1]+=t,rmn-=t;}}return flow-rmn;
}int dinic()
{int r=0;while(bfs()) r+=dfs();return r;
}
int main()
{int s,t;cin>>n>>m>>s>>t;memset(h,-1,sizeof h);S=0,T=n+1;for(int i=1;i<=m;i++){int a,b,c,d;cin>>a>>b>>c>>d;add(a,b,d-c);A[a]-=c,A[b]+=c;}int tot=0;for(int i=1;i<=n;i++){if(A[i]>0)add(S,i,A[i]),tot+=A[i];else if(A[i]<0)add(i,T,-A[i]);}add(t,s,0x3f3f3f3f);if(dinic()!=tot) cout<<"No Solution\n";else{int f1=f[idx-1];S=t,T=s;f[idx-1]=f[idx-2]=0; //删去 t->s的边cout<<f1-dinic()<<'\n';}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Sangmado 公共基础类库

Sangmado&#xff08;发音 /sɔŋmɑːdu:/ ‘桑麻渡’&#xff09;涵盖了支撑 .NET/C# 项目开发的最基础的公共类库&#xff0c;为团队在不断的系统开发和演进过程中发现和积累的最公共的代码可复用单元。Sangmado 公共类库设计原则&#xff1a;独立性&#xff1a;不与任何业务…

牛客挑战赛48E-速度即转发【带修莫队,分块】

正题 题目链接:https://ac.nowcoder.com/acm/contest/11161/E 题目大意 给出nnn个数字的一个序列&#xff0c;mmm个操作。 给出l,r,kl,r,kl,r,k&#xff0c;求一个最大的xxx使得∑ilrmax{ai−x,0}≥k\sum_{il}^rmax\{a_i-x,0\}\geq k∑ilr​max{ai​−x,0}≥k单点修改 解题思…

L2-002 链表去重

给定一个带整数键值的链表 L&#xff0c;你需要把其中绝对值重复的键值结点删掉。即对每个键值 K&#xff0c;只有第一个绝对值等于 K 的结点被保留。同时&#xff0c;所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15&#xff0c;你需要输出去重后…

【模板】卡特兰数

ACM模板 目录Catalan数证明卡特兰数应用Catalan数证明 1.卡特兰数递推式&#xff1a; an{1,n0∑i0n−1aian−1−i,n>0a_n\begin{cases} 1,n0\\\sum_{i0}^{n-1}a_ia_{n-1-i},n>0\end{cases} an​{1,n0∑i0n−1​ai​an−1−i​,n>0​ 2.卡特兰数组合数&#xff1a; an…

【活动(深圳)DevOps/.NET 微服务 秋季分享会】火热报名中!

无论身处开发还是运维岗位&#xff0c;您一定深刻地感受着业务需求带来的快速交付压力。在科技迅速发展的时代&#xff0c;传统行业积极开展数字化转型以在激烈竞争中脱颖而出&#xff0c;新兴行业不停歇地验证业务模式以找准市场定位&#xff1b;软件与行业变得密不可分&#…

P7443-加边【博弈论】

正题 题目链接:https://www.luogu.com.cn/problem/P7443?contestId41429 题目大意 nnn个点的一棵有根树&#xff0c;两个人从一号点开始进行有向图博弈。 告诉你Alice是先手还是后手&#xff0c;然后你可以选择加一条链接(u,v)(u,v)(u,v)的有向边&#xff0c;权值为AauBavA\…

L2-004 这是二叉搜索树吗?

一棵二叉搜索树可被递归地定义为具有下列性质的二叉树&#xff1a;对于任一结点&#xff0c; 其左子树中所有结点的键值小于该结点的键值&#xff1b; 其右子树中所有结点的键值大于等于该结点的键值&#xff1b; 其左右子树都是二叉搜索树。 所谓二叉搜索树的“镜像”&#x…

【模板】序列自动机

ACM模板 目录构建序列自动机子序列查询构建序列自动机 ne[i][j]存的是在字符串 s 中第 iii 位后面第一个 j(0<j<26)j(0<j<26)j(0<j<26) 字母出现的位置。 void build(char s[]) {int nstrlen(s1);for(int in;i;i--){for(int j0;j<26;j)ne[i-1][j]ne[i][j]…

微软正式发布Azure IoT Central

微软正式发布Azure IoT Central&#xff0c;这是一个面向物联网的软件即服务解决方案。借助该服务&#xff0c;微软旨在提供一种设计、开发、配置和管理IoT设备的低代码方式&#xff0c;同时提供开箱即用的安全性、可伸缩性以及与流程&应用程序集成。Azure IoT Central构建…

ARC115E-LEQ and NEQ【容斥,dp,线段树】

正题 题目链接:https://atcoder.jp/contests/arc115/tasks/arc115_d 题目大意 nnn个数字的序列xxx&#xff0c;第xi∈[1,Ai]∩Zx_i\in [1,A_i]\cap Zxi​∈[1,Ai​]∩Z。要求相邻的不同&#xff0c;求方案数。 1≤n≤5105,1≤Ai≤1091\leq n\leq 5\times 10^5,1\leq A_i\leq 1…

点分治(树分治)

文章目录介绍&#xff1a;题目&#xff1a;做法&#xff1a;模板题 [P3806 【模板】点分治1](https://www.luogu.com.cn/problem/P3806)代码&#xff1a;介绍&#xff1a; 将原问题分解成若干相同形式&#xff0c;相互独立的子问题&#xff0c;各个击破 一般用来解决有关树上路…

【模板】KMP算法、fail树

ACM模板 目录KMP字符串Fail失配树KMP字符串 肖然大佬视频讲解 子串&#xff1a; 从原串中选取连续的一段&#xff0c;即为子串&#xff08;包括空串&#xff09; 前缀&#xff1a; pre(s,k)pre(s,k)pre(s,k) 为 s 前 k 个字符构成的子串 后缀&#xff1a; suf(s,k)suf(s,k)suf…

.NET Standard 2.1 公布

原文: Announcing .NET Standard 2.1校对: Cloud自从大约一年前发布 .NET Standard 2.0以来&#xff0c;我们已经向 .NET Core 2.1 发布了两个更新&#xff0c;并即将发布 .NET Core 2.2 。 现在是时候更新 Standard 了&#xff0c;包括一些新的概念以及一些小改进&#xff0c;…

CF708E-Student‘s Camp【数学期望,dp】

正题 题目链接:https://www.luogu.com.cn/problem/CF708E 题目大意 有n∗mn*mn∗m的矩形网格&#xff0c;然后每次每行最左边和最右边的格子各有pcdp\frac{c}{d}pdc​的概率会消失&#xff0c;进行kkk次。 求最后所有格子依旧四联通的概率&#xff0c;在%(1097)\%(10^97)%(1…

P3806 【模板】点分治1

模板题 P3806 【模板】点分治1 题目描述 给定一棵有 n 个点的树&#xff0c;询问树上距离为 k 的点对是否存在。 详讲 关于点分治具体内容可以看这个 这里主要是详细讲讲代码&#xff1a; getrt是用来求重心&#xff0c;我们利用树型dp的思维来做&#xff0c;即找到该节点所…

ASP.NET Core中使用GraphQL - 第二章 中间件

前文&#xff1a;ASP.NET Core中使用GraphQL - 第一章 Hello World中间件如果你熟悉ASP.NET Core的中间件&#xff0c;你可能会注意到之前的博客中我们已经使用了一个中间件&#xff0c;这个中间件负责输出了当前查询的结果。中间件的定义&#xff1a;中间件是装载在应用程序管…

【模板】AC自动机

ACM模板 目录插入以及构建AC自动机【模板】AC自动机&#xff08;二次加强版&#xff09;ac自动机fail树上dfs序建可持久化线段树插入以及构建AC自动机 #include<queue> #include<string> const int N200010; struct node {int chd[26],fail,cnt; }tree[N]; void i…

ASP.NET Core中Ocelot的使用:基于服务发现的负载均衡

本系列相关文章&#xff1a;《ASP.NET Core中Ocelot的使用&#xff1a;API网关的应用》《ASP.NET Core中Ocelot的使用&#xff1a;基于Spring Clound Netflix Eureka的动态路由》本文将基于前两篇文章所述内容&#xff0c;继续介绍如何在服务发现和动态路由的基础上&#xff0c…

CF643F-Bears and Juice【组合数学】

正题 题目链接:https://www.luogu.com.cn/problem/CF643F 题目大意 题目有点奇怪就直接放翻译了 有 nnn 只熊和若干桶果汁和恰好一桶酒&#xff0c;每一天每只熊会选择一些桶&#xff08;可能不选&#xff09;并各喝一 杯&#xff0c;喝到酒的熊会去睡觉并不再回来&#xff…

【模板】Manacher算法

ACM模板 目录初始化以及构造初始化以及构造 数组下标从1开始即cin>>s1 由于奇回文串和偶回文串某些性质不同&#xff0c;我们首先通过init()操作使得新串中所有回文串的长度都变成奇数&#xff0c;返回值是新串的长度&#xff08;原串中的下标i对应新串中的2i&#xff09…