[洛谷 P3376] 网络最大流 | 模板 (Dinic算法) 入门

简介: 题目描述如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。输入格式第一行包含四个正整数 n nn,m mm,s ss,t tt,分别表示点的个数、有向边的个数、源点序号、汇点序号。接下来M行每行包含三个正整数 ui ,vi,wi ,表示第 i 条有向边从 ui 出发,到达 vi,边权为 wi即该边最大流量为 wi)。输出格式一行,包含一个正整数,即为该网络的最大流。

题目链接


题目描述


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


输入格式


第一行包含四个正整数 n nn,m mm,s ss,t tt,分别表示点的个数、有向边的个数、源点序号、汇点序号。


接下来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 40
50


样例输入输出 1 解释


80e888d89c2a411c9826d78ae5af2112.png

b2af0b70a4f244cba727e057f5c6d871.png


层次图:


假设在残量网络中,起点到结点u的距离为dist(u) ,我们把dist(u)看作是结点u的的层次。只保留每个点出发到下一个层次的弧,得到的图就叫做层次图,层次图上的任意路径都是“起点-> 层次1-> 层次2-> …"这样的顺序,不难发现,每条这样的路径都是s->t 的最段路


阻塞流:


阻塞流实际上就是指不考虑反向弧时的”极大流“,对应到程序里就是从起点开始在层次图中DFS,没找到一条路就进行增广

多次增广之后层次图中不存在s->t的路径,合称阻塞流

Dinic 最多会进行计算n-1 次阻塞流(每次沿阻塞流增广之后,最大距离至少会增加1),而每次阻塞流的计算时间均不超过O ( m n ) O(mn)O(mn) ,实际上比这个理论界好的多


从宏观上讲,Dinic算法就是不停地用BFS来进行构造层次图,然后用阻塞流来增广。

struct Edge {
    int u, v;
    ll cap, flow;
    Edge(int _u, int _v, ll _cap, ll _flow) {
        u = _u, v = _v;
        cap = _cap, flow = _flow;
    }
};
struct Dinic {
    vector<Edge> edge;
    vector<int> G[maxn];
    ll dis[maxn],cur[maxn];
    int n,s,t;
    bool vis[maxn];
    void init(int x,int _s,int _t){
      n = x;
      for(int i = 0;i <= n;i++) G[i].clear();
      s = _s,t = _t;
      edge.clear();
    }
    void add(int u,int v,ll cap){
      edge.push_back(Edge(u,v,cap,0));
      edge.push_back(Edge(v,u,0,0));
      G[u].push_back(edge.size() - 2);
      G[v].push_back(edge.size() - 1);
    }
    bool bfs(int s,int t){
      queue<int> que;
      memset(vis,0,sizeof vis);
      // memset(dis,0,sizeof dis);
      dis[s] = 0;
      que.push(s);
      vis[s] = 1;
      while(que.size()){
        int u = que.front();
        que.pop();
        for(int i=0;i<G[u].size();i++){
          int id = G[u][i];
          int to = edge[id].v;
          if(!vis[to] && edge[id].cap > edge[id].flow){
            dis[to] = dis[u] + 1;
            que.push(to);
            vis[to] = 1;
          }
        }
      }
      return vis[t];
    }
    ll dfs(int s,int t,ll rest){
      if(s == t || rest == 0) return rest;
      ll sum = 0LL;
      ll Flow = 0, f;
      for(ll& i = cur[s];i < G[s].size();i ++){
        Edge& e = edge[G[s][i]];
        if(dis[s] + 1 == dis[e.v] && (f = dfs(e.v ,t,min(rest,e.cap - e.flow))) > 0){
          e.flow += f;
          edge[G[s][i] ^ 1].flow -= f;
          Flow += f;
          rest -= f;
          if(rest == 0) break;
        }
      }
      return Flow;
    }
    ll getMaxFlow(int s,int t){
      ll ans = 0;
      while(bfs(s,t)) {
        memset(cur,0,sizeof cur);
        ans += dfs(s,t,0x3f3f3f3f);
      }
      return ans;
    }
} solve;
int main() {
    int n = read,m = read,s = read,t = read;
    solve.init(n,s,t);
    for(int i=1;i<=m;i++){
      ll u = read,v = read,cap = read;
      solve.add(u,v,cap);
    }
    cout << solve.getMaxFlow(s,t) <<endl;
    return 0;
}




目录
相关文章
|
4天前
|
存储 算法
算法入门:专题二---滑动窗口(长度最小的子数组)类型题目攻克!
给定一个正整数数组和目标值target,找出总和大于等于target的最短连续子数组长度。利用滑动窗口(双指针)优化,维护窗口内元素和,通过单调性避免重复枚举,时间复杂度O(n)。当窗口和满足条件时收缩左边界,更新最小长度,最终返回结果。
|
1月前
|
传感器 机器学习/深度学习 算法
【UASNs、AUV】无人机自主水下传感网络中遗传算法的路径规划问题研究(Matlab代码实现)
【UASNs、AUV】无人机自主水下传感网络中遗传算法的路径规划问题研究(Matlab代码实现)
|
1月前
|
机器学习/深度学习 算法 调度
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
224 0
|
14天前
|
存储 机器学习/深度学习 监控
网络管理监控软件的 C# 区间树性能阈值查询算法
针对网络管理监控软件的高效区间查询需求,本文提出基于区间树的优化方案。传统线性遍历效率低,10万条数据查询超800ms,难以满足实时性要求。区间树以平衡二叉搜索树结构,结合节点最大值剪枝策略,将查询复杂度从O(N)降至O(logN+K),显著提升性能。通过C#实现,支持按指标类型分组建树、增量插入与多维度联合查询,在10万记录下查询耗时仅约2.8ms,内存占用降低35%。测试表明,该方案有效解决高负载场景下的响应延迟问题,助力管理员快速定位异常设备,提升运维效率与系统稳定性。
52 4
|
16天前
|
存储 算法
算法入门:专题一:双指针(有效三角形的个数)
给定一个数组,找出能组成三角形的三元组个数。利用“两边之和大于第三边”的性质,先排序,再用双指针优化。固定最大边,左右指针从区间两端向内移动,若两短边之和大于最长边,则中间所有组合均有效,时间复杂度由暴力的O(n³)降至O(n²)。
|
15天前
|
存储 算法 编译器
算法入门:剑指offer改编题目:查找总价格为目标值的两个商品
给定递增数组和目标值target,找出两数之和等于target的两个数字。利用双指针法,left从头、right从尾向中间逼近,根据和与target的大小关系调整指针,时间复杂度O(n),空间复杂度O(1)。找不到时返回{-1,-1}。
|
20天前
|
机器学习/深度学习 算法
采用蚁群算法对BP神经网络进行优化
使用蚁群算法来优化BP神经网络的权重和偏置,克服传统BP算法容易陷入局部极小值、收敛速度慢、对初始权重敏感等问题。
162 5
|
24天前
|
机器学习/深度学习 传感器 算法
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
|
1月前
|
机器学习/深度学习 并行计算 算法
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
|
1月前
|
算法 数据挖掘 区块链
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)
基于遗传算法的多式联运车辆路径网络优优化研究(Matlab代码实现)