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=u​f(i)−∑fromi=u​f(i)即流入减去流出
  • 若A(u)>0A(u)>0A(u)>0,源点SSS向uuu点连边,容量是A(u)A(u)A(u)
  • 若A(u)<0A(u)<0A(u)<0,uuu点向汇点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}fs→t​=−ft→s​ 这也是为什么相减的原因

有源汇上下界最小流

#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';}
}

【模板】最大流之上下界可行流相关推荐

  1. 一篇网络流 基本模型超全总结(最大流 费用流 多源汇最大流 上下界可行流) 思路+代码模板

    文章目录 一.网络流与最大流 二.网络流三个基本性质 三.重要定义定理 四.最大流算法 <Ⅰ> Edmonds-Karp算法(EK算法) 1.EK算法 2.算法思想: 3.代码模板 4.模 ...

  2. loj#115. 无源汇有上下界可行流

    \(\color{#0066ff}{ 题目描述 }\) 这是一道模板题. \(n\) 个点,\(m\) 条边,每条边 \(e\) 有一个流量下界 \(\text{lower}(e)\) 和流量上界 \ ...

  3. 无源汇有上下界可行流(网络流进阶)

    无源汇有上下界可行流(也就是循环流) 模型:一个网络,求出一个流,使得每条边的流量必须>=Li且<=Hi, 每个点必须满足总流入量=总流出量(流量守恒)(这个流的特点是循环往复,无始无终) ...

  4. 【bzoj2406】矩阵 二分+有上下界可行流

    题目描述 输入 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. 输出 第一行,输出最小的答案: 样例输入 2 2 0 1 2 1 0 1 样例输出 1 ...

  5. BZOJ 2406 LuoguP4194 矩阵 有上下界可行流

    分析: 这道题乍一看--卧槽这都什么玩意-- 然后发现给了个A矩阵,要求一个可行的B矩阵,使得矩阵C=A-B的每一行的和的绝对值和每一列的和的绝对值的最大值最小-- 好拗口啊-- 什么最大值最小之类的 ...

  6. 【ACWing】2188. 无源汇上下界可行流

    题目地址: https://www.acwing.com/problem/content/2190/ 给定一个包含nnn个点mmm条边的有向图,每条边都有一个流量下界和流量上界.求一种可行方案使得在所 ...

  7. 网络流__4 上下界可行流

    网络流 __4 上下界可行流 对于容量有上下界规范的网络流问题 无源汇上下界可行流 n个点m条边的有向图,每条边有一个流量下界和流量上界规范,求是否存在一个可行流 设原网络为(G,F),变换后网络为( ...

  8. 【zoj2314】Reactor Cooling 有上下界可行流

    题目描述 The terrorist group leaded by a well known international terrorist Ben Bladen is buliding a nuc ...

  9. bzoj 2406 矩阵——有源汇上下界可行流

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2406 二分答案.把 b 的 n 个行作为一排, m 个列作为一排,每行和每列之间连上下界为 ...

最新文章

  1. (转载)如何学好iphone游戏开发
  2. pymongo连接mongodb的replset
  3. A Step By Step Guide to Tomcat Performance Monitoring【转】
  4. 【LSH源码分析】p稳定分布LSH算法
  5. mysql datetime类型按天查询_mysql 时间相关sql , 按天、月、季度、年等条件进行查询...
  6. Java 判断是否包含指定的子串 contains()
  7. poj 3278 Catch That Cow (bfs)
  8. Linux学习总结(6)——CenterOS7安装mysql5.5的方法
  9. STM32工作笔记0068---SPI同步通信Flash读写实验
  10. SqlServer 查询表
  11. C++构造函数初始化列表与赋值
  12. java8接口写静态方法_Java 8接口更改–静态方法,默认方法
  13. 【Unity】UGUI无法修改UI元素的Pivot锚点位置
  14. wps下一步快捷键_办公必备|终于整理完了这74个WPS最常用快捷键
  15. java梯形面积代码_Java面向对象练习题之梯形面积
  16. python常用数学符号_ML-常用数学符号(示例代码)
  17. 移远百科 | GNSS定位技术知多少
  18. Windows 2003安装和配置活动目录服务 zz
  19. Web安全之常见面试题总结
  20. 如何玩转淘宝直通车?提高转化率?

热门文章

  1. 用html制作篮球网页,篮球网站的设计与实现).doc
  2. 简单计算机面试题库及答案_计算机专业复试面试问题含答案
  3. html下拉菜单的子目录,html - 带有下拉菜单的子菜单的垂直下拉菜单 - 堆栈内存溢出...
  4. sql同时向两个表插入数据_SQL入门-数据库和客户端的安装,表的创建和数据插入...
  5. es6添加删除class_es6中class类的使用
  6. eeprom stm8l 擦除 读写_[STM8L]EEPROM操作读与写
  7. vue 一个组件内多个弹窗_论如何用Vue实现一个弹窗-一个简单的组件实现
  8. [mybatis]动态sql_if_where_trim判断OGNL
  9. LeetCode 82 删除排序链表中的重复元素||-中等
  10. Pearls POJ - 1260(区间记忆化搜索)