当前位置: 首页 > news >正文

网络流学习笔记

模板

标准网络流 (简略)

这里只讲 Dinic。

通过 BFS 不断求出增广路(流量不为零的路径),并记录到原点的距离。然后跑 DFS,往距离增大的方向跑以保证时间复杂度。把增广路上的边减去通过的流量,其反边加上通过的流量。不断重复上述过程直到无法找到新的的增广路。

时间复杂度为 \(O(n^2m)\),通常跑不满,特殊图的情况下会更快。

参考实现代码
#include<bits/stdc++.h>
#define fst first
#define sec second
#define mkp(a,b) make_pair(a,b)
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int maxn=205,maxm=10200,inf=1e9+1;
const LL linf=1e18+1;
void read(int& x){char c;bool f=0;while((c=getchar())<48) f|=(c==45);x=c-48;while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;x=(f ? -x : x);
}
struct FLOW{int head[maxn],nxt[maxm<<1];tuple<int,LL> e[maxm<<1];int mp_cnt=-1;void init_mp(){memset(head,-1,sizeof(head));mp_cnt=-1;}void add_edge(int u,int v,LL c){e[++mp_cnt]=make_tuple(v,c);nxt[mp_cnt]=head[u],head[u]=mp_cnt;e[++mp_cnt]=make_tuple(u,0);nxt[mp_cnt]=head[v],head[v]=mp_cnt;}int n,s,t;int dis[maxn],cur[maxn];void init(int ni,int si,int ti){init_mp(),n=ni,s=si,t=ti;}bool bfs(){queue<int> q;q.push(s);fill(dis+1,dis+n+1,inf),dis[s]=0;while(!q.empty()){int u=q.front(); q.pop();if(u==t) return true;for(int i=head[u];~i;i=nxt[i]){int v; LL c; tie(v,c)=e[i];if(c&&dis[u]+1<dis[v]){dis[v]=dis[u]+1;q.push(v);}}}return false;}LL dfs(int u,LL f){if(u==t) return f;LL sum=0;for(int i=cur[u];(~i)&&f;i=nxt[i]){int v; LL c; tie(v,c)=e[i],cur[u]=i;if(dis[v]!=dis[u]+1||(!c)) continue;LL fi=dfs(v,min(f,c));if(!fi) dis[v]=-1;sum+=fi,f-=fi,get<1>(e[i])-=fi,get<1>(e[i^1])+=fi;}return sum;}LL solve(){LL ans=0;while(bfs()){for(int i=1;i<=n;i++) cur[i]=head[i];ans+=dfs(s,linf);}return ans;}
};
FLOW fw;
int main(){int n,m,s,t; read(n),read(m),read(s),read(t);fw.init(n,s,t);for(int i=1;i<=m;i++){int u,v,c; read(u),read(v),read(c);fw.add_edge(u,v,c);}printf("%lld",fw.solve());return 0;
}
//^o^

最小费用最大流

每条边有单位流量的费用,保证流量最大的同时,最小的费用。

把 BFS 换成 SPFA 即可。

参考实现代码
#include<bits/stdc++.h>
#define fst first
#define sec second
#define mkp(a,b) make_pair(a,b)
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int maxn=5010,maxm=4e6+10,inf=1e9+1;
const LL linf=1e18+1;
void read(int& x){char c;bool f=0;while((c=getchar())<48) f|=(c==45);x=c-48;while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;x=(f ? -x : x);
}
struct FLOW{int head[maxn],nxt[maxm],mp_cnt;tuple<int,LL,LL> e[maxm];int n,s,t;LL maxf,minc;void init(int ni,int si,int ti){n=ni,s=si,t=ti,maxf=minc=0;fill(head+1,head+ni+1,-1),mp_cnt=-1;}void add_edge(int u,int v,LL f,LL c){e[++mp_cnt]=make_tuple(v,f,c);nxt[mp_cnt]=head[u],head[u]=mp_cnt;e[++mp_cnt]=make_tuple(u,0,-c);nxt[mp_cnt]=head[v],head[v]=mp_cnt;}bool ins[maxn];int cur[maxn];LL dis[maxn];bool SPFA(){fill(dis+1,dis+n+1,linf),fill(ins+1,ins+n+1,0);queue<int> q; q.push(s); ins[s]=1,dis[s]=0;while(!q.empty()){int u=q.front(); q.pop(),ins[u]=0;for(int i=head[u];~i;i=nxt[i]){int v; LL f,c; tie(v,f,c)=e[i];if((!f)||dis[u]+c>=dis[v]) continue;dis[v]=dis[u]+c; if(!ins[v]) { q.push(v),ins[v]=1; }}}return dis[t]^linf;}LL dfs(int u,LL lst){if(u==t) return lst;ins[u]=1; LL sum=0;for(int i=cur[u];(~i)&&lst;i=nxt[i]){cur[u]=i;int v; LL f,c; tie(v,f,c)=e[i];if((!f)||dis[u]+c!=dis[v]||ins[v]) continue;LL p=dfs(v,min(lst,f));if(!p) dis[v]=-linf;sum+=p,get<1>(e[i])-=p,get<1>(e[i^1])+=p,lst-=p;minc+=p*c;}ins[u]=0;return sum;}void work(){while(SPFA()){for(int i=1;i<=n;i++) cur[i]=head[i],ins[i]=0;maxf+=dfs(s,linf);}}
};
FLOW fw;
int n,m,s,t;
int main(){read(n),read(m),read(s),read(t);fw.init(n,s,t);	for(int i=1;i<=m;i++){int u,v,f,c; read(u),read(v),read(f),read(c);fw.add_edge(u,v,f,c);}fw.work();printf("%lld %lld",fw.maxf,fw.minc);return 0;
}
//^o^

无原汇上下界的网络流

每条边都有一个流量下界和流量上界,无源汇就是说每个点都满足流入量等于流出量。

假设每条边的流量设置为其流量下界,然后会发现有些点并没有流量平衡,统计出每个点缺失或多余的流量。然后以每条边的最大流量减去最小流量作为流量限制,新建源汇点 S 和 T,原先缺失流量的点向 T 连边,流量限制为缺失的流量,原先多余流量的点从 S 连向它,流量限制为多余的流量,跑最大流。相当于把流量分成了两部分,一部份是下界流量,必须有,但是会有缺失或多余,一部份是差量网络,需要补足下界网络的流量缺失和多余,于是我们就用新的源汇点来模拟这种缺失和多余。注意上文中加粗的部分,这里容易搞反,不是说缺失了就要向 T 连边补足,而是要模拟这种缺失,以达到在两个部分的网络流重新加在一起的时候能够保持流量平衡,多余的时候同理。所以在检查该网络流是否可行是,只需要查验新补上的边是否全部流满就可以了,真实流量就是差量网络中的流量加上下界流量。

梳理一下连边:

  • 原图中 \((u,v,l,r)\) 的边,连边 \((u,v,r-l)\)
  • 若点 \(u\) 在下界网络中多向外流了 \(f\) 的流量,则连边 \((u,t,f)\)。若少流入了 \(f\) 的流量,则连边 \((s,u,f)\)

有源汇上下界网络流

由汇点向源点之间连一条容量为 \(\inf\) 的边,这样变成了无原汇上下界的网络流,同理求解即可。

注意:如上方法跑出的都是上下界网络流中的最小可行流,如需最大流,去除补上的边,算出每条边的剩余流量,再跑最大流。

带有负费用圈的网络流

对于一条负费用的边,直接使其满流,并加入一条容量相同,费用相反,方向相反的边用于退流,强制满流可以用上下界相同网络流实现。

一些关于网络流的常见思路和套路

最小割

最小割,就是在图中去除边,使得 S 和 T 不连通,需要去除边的最小边权和。

流量设为边权,最小割 = 最大流。

总点数 - 最大匹配 = 最小链覆盖 = 最大独立集

最大匹配是指在一个图中,包含边数最多的匹配,且每个顶点至多被一条边覆盖。

二分图的最大匹配,做法为源点连向左边的点,右边的点连向汇点,所有边的流量均为 1,跑最大流。

有向图的最大匹配,做法为把一个点拆成入度和出度,再连成二分图后跑最大流。(入度点不用连出度点)

最小链覆盖:覆盖所有点的最少的链的数量。

最大独立集:在图中取点,使得其中任意一个点都不能到达其他点,这样能取得最多的点得数量。

棋盘上的放置问题

通常要找出两类格子,一条有向边表示选了这个格子就不能选另一个格子,于是就得到一张二分图。源点连向左边的点,右边的点连向汇点,这些边权均为 1,表示切割代价为 1,中间的边边权为 \(\inf\),表示不能切割,找到最小割模型。

还有很多稀奇古怪的建图方式就等你探索啦!

http://www.jsqmd.com/news/405872/

相关文章:

  • 以太坊节点发现背后的分布式哈希表(DHT)与 Kademlia 原理解析 - 若
  • sql注入之数据类型
  • 2026年3月谷歌独立站多语种建站公司/服务商深度评测推荐:昊客网络引领榜单 - 深圳昊客网络
  • 全流程适配,有哪些好用的写作软件,从选题到排版一键搞定
  • 压空间 st 表
  • 推荐几个靠谱的AI写论文辅助工具,润色+降重+文献引用全覆盖
  • B3644 【模板】拓扑排序 / 家谱树
  • 2026 中国网站建设公司深度评测:十大口碑品牌推荐 - 品牌企业推荐师(官方)
  • Comucopia丰饶角曲面3D旋转动画解析_C++精灵库可视化案例
  • [AI提效-34]- 2026年企业数字化服务对接平台深度对比分析
  • P10440 [JOIST 2024] 环岛旅行 / Island Hopping
  • 常州全屋定制源头工厂推荐 - 品牌企业推荐师(官方)
  • 节后胖三斤?2026年科学减脂方案:安全长效、不反弹的代餐产品实测排名 - 品牌企业推荐师(官方)
  • 家装建材行业GEO公司权威排名(2026最新) - 品牌企业推荐师(官方)
  • 石笼网水利工程资质齐全:企业项目拓展核心策略解析——以衡水九耀堤坡防护工程有限公司为例 - 品牌企业推荐师(官方)
  • 节后胖三斤?2026年科学减脂方案:安全长效、不反弹的节后体重管理权威指南 - 品牌企业推荐师(官方)
  • 不同类型的网站建设在前期规划时,核心差异点是什么? - 品牌企业推荐师(官方)
  • 2026年网站建设公司TOP10盘点:谁才是真正好用的行业黑 - 品牌企业推荐师(官方)
  • 2026年3月谷歌独立站多语种建站公司/服务商深度评测推荐:深圳昊客网络 - 深圳昊客网络
  • 沈阳AI获客公司选择 - 品牌企业推荐师(官方)
  • 视频孪生之上:三维轨迹张量建模构建可预测空间模型——基于时间 × 空间 × 速度向量耦合的趋势级风险推演体系
  • 超越视频孪生:镜像视界矩阵视频融合的空间级表达革命——统一空间坐标体系驱动的跨摄像连续表达 × 三维坐标反演 × 趋势级风险计算基础引擎
  • [RAG实战] Dify 多日期提问召回不全?一次彻底解决“检索被稀释”的工程方案(含完整实现思路)
  • 深度学习中的概念:信息熵、信息增益与纯度
  • 深度解读!提示工程架构师对AI与提示设计未来的见解
  • 【每日一题】LeetCode 1461. 检查一个字符串是否包含所有长度为 K 的二进制子串
  • 基于Eureka的大数据服务链路追踪实现方案
  • 借助大数据技术改进电商运营效率
  • 2025科研AI智能体技术趋势:超级计算架构师的3大能力储备
  • 在Windows中用命令行编译c++Windows程序