洛谷 P3376:[模板] 网络最大流 ← Dinic 算法

【题目来源】
https://www.luogu.com.cn/problem/P3376
https://www.acwing.com/problem/content/2174/

【题目描述】
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。

【输入格式】
第一行包含四个正整数 n,m,s,t,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来 m 行每行包含三个正整数 ui,vi,wi,表示第 i 条有向边从 ui 出发,到达 vi,边权为 wi(即该边最大流量为 wi)。

【输出格式】
一行,包含一个正整数,即为该网络的最大流。

【输入样例】
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 30

【输出样例】
50

【数据范围】
对于 30% 的数据,保证 n≤10,m≤25。
对于 100% 的数据,保证 1≤n≤200,1≤m≤5000,0≤w<2^31。

【算法分析】
● Dinic 算法被认为是网络流问题的"瑞士军刀"。在算法竞赛和面试中,掌握了 Dinic 算法就解决了 90% 的最大流问题。

● 网络流常用示意图(https://blog.csdn.net/hnjzsyjyj/article/details/139595477
在残量网络中找可增广路;
在实流网络中沿可增广路增流,在残量网络中沿可增广路减流。

增广路定理:设 flow 是网络 G 的一个可行流,如果不存在从源点 s 到汇点 t 关于 flow 的可增广路p,则 flow 是 G 的一个最大流。

● 残量网络(Residual Network)是网络流算法的核心概念。它不是独立构建的数据结构,而是基于原网络和当前流量动态计算出的"可用容量"的表示。
对于原网络 G=(V,E) 中的每条边 (u,v),其容量为 c(u,v),当前流量为 f(u,v)。残量网络包含两类边:
(1)正向边:剩余容量 c(u,v)−f(u,v)
(2)反向边:剩余容量 f(u,v)

● 利用"^1"运算表示反向边
由于网络流是有向有权图,因此可以选择链式前向星(https://blog.csdn.net/hnjzsyjyj/article/details/139369904)存图。对一个数连续执行两次"^1"运算后,便会得到自身。这恰好与网络流中"反向边的反向边等于自身"不谋而合。因此,在网络流的算法实现中,我们可以利用"^1"运算来表示反向边。

● Dinic 算法中不需要显式构建完整的残量网络,而是通过修改边的容量来隐式维护。

● Dinic 不是简单的 DFS,而是"BFS 分层 + DFS 多路增广"的完美结合。其核心流程如下:
(1)BFS 构建分层图:从源点出发,计算每个节点到源点的最短距离(边数),形成"层次"。在残量网络 中,规定只能从低层走向高层(d[v] = d[u] + 1),这有效避免了 DFS 在环里绕圈子。
(2)DFS 多路增广:在分层图上进行 DFS,一次性找出当前层次限制下所有可能的增广路,并更新流量。
(3)重复:当 BFS 无法到达汇点时,算法结束。

● 在 Dinic 算法中,用 STL 的 std::queue 写 BFS 层级图构建,确实很容易在性能敏感的大规模图(特别是稠密图、多次 BFS)中成为性能瓶颈,甚至导致 TLE。

【算法代码】
(1)本题代码中,dinic() 函数的返回值为 long long 型。
(2)由于 dinic() 函数需要建反向边,所以代码中的边数,至少需要设为题目陈述中边数的两倍。
(3)f[i] 表示第 i 条边的「剩余容量」。不是总流量,不是已用流量,是还能流多少!初始时,f[i] = 边的容量。流完后,f[i] 减少,f[i^1] 增加(反悔用)。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N=1e4+5,M=2e5+5;
const int INF=INT_MAX;

int n,m,S,T;
int h[N],e[M],ne[M],f[M],idx;
int d[N],cur[N],q[N];

void add(int a,int b,int w) {
    f[idx]=w,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    f[idx]=0,e[idx]=a,ne[idx]=h[b],h[b]=idx++;
}

bool bfs() {
    memset(d,-1,sizeof d);
    int hh=0,tt=0;
    q[0]=S,d[S]=0;

    while(hh<=tt) {
        int u=q[hh++];
        for(int i=h[u]; ~i; i=ne[i]) {
            int v=e[i];
            if(d[v]==-1 && f[i]) {
                d[v]=d[u]+1;
                q[++tt]=v;
            }
        }
    }
    return d[T]!=-1;
}

int dfs(int u,int lim) {
    if(u==T) return lim;
    int flow=0;
    for(int i=cur[u]; ~i && flow<lim; i=ne[i]) {
        cur[u]=i;
        int v=e[i];
        if(d[v]==d[u]+1 && f[i]) {
            int t=dfs(v,min(f[i],lim-flow));
            if(!t) d[v]=-1;
            f[i]-=t,f[i^1]+=t,flow+=t;
        }
    }
    return flow;
}

LL dinic() {
    LL r=0,flow=0;
    while(bfs()) {
        for(int i=1; i<=n; i++) cur[i]=h[i];
        while(flow=dfs(S,INF)) r+=flow;
    }
    return r;
}

int main() {
    memset(h,-1,sizeof h);
    cin>>n>>m>>S>>T;
    while(m--) {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    cout<<dinic()<<endl;
    return 0;
}

/*
in:
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 30

out:
50
*/

【参考文献】
https://www.acwing.com/video/1537/
https://www.acwing.com/solution/content/68463/
https://zhuanlan.zhihu.com/p/573015182
https://www.acwing.com/file_system/file/content/whole/index/content/6610796/
https://www.acwing.com/file_system/file/content/whole/index/content/6511769/
https://www.acwing.com/file_system/file/content/whole/index/content/10718893/
https://blog.csdn.net/hnjzsyjyj/article/details/139595477
https://www.luogu.com.cn/problem/solution/P3376
https://www.cnblogs.com/bianchengmao/p/16713542.html
https://www.acwing.com/file_system/file/content/whole/index/content/10718684/

相关推荐
hansang_IR6 个月前
【记录】网络流最小割建模三题
c++·算法·网络流·最小割
CUC-MenG7 个月前
2025牛客国庆集训派对day5 K E 个人题解
图论·网络流·状态压缩·随机优化·树上dp·网络流费用流
pystraf1 年前
模板分享:网络最小费用流
c++·算法·图论·网络流
呆萌的代Ma1 年前
下载并使用CICFlowMeter提取网络流特征(Windows版本)
windows·网络流
大灰狼19132 年前
【怎样基于Okhttp3来实现各种各样的远程调用,表单、JSON、文件、文件流等待】
java·springboot·网络流·okhttp3·文件流传输
数学收藏家2 年前
网络流之最小费用最大流(dinic+SPFA 模板)
网络流
QuantAsk2 年前
CF1615H-Reindeer Games【保序回归,整体二分,网络流】
codeforces·网络流·保序回归·整体二分
一根老麻花2 年前
图论 | 网络流的基本概念
网络·图论·网络流
星河依旧长明2 年前
AcWing算法进阶课-1.9.1Dinic/ISAP求最小割
算法·图论·网络流