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

简介: 题目描述如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。输入格式第一行包含四个正整数 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.pngb2af0b70a4f244cba727e057f5c6d871.png

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 ISAP {
    vector<Edge> edge;
    vector<int> G[maxn];
    ll dis[maxn], cur[maxn];
    int n, s, t;
    ll p[maxn], num[maxn];
    bool vis[maxn];
    void init(int _n, int _s, int _t) {
        this->n = _n, this->s = _s, this->t = _t;
        for (int i = 1; i <= _n; i++) G[i].clear();
        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));
        int siz = edge.size();
        G[u].push_back(siz - 2);
        G[v].push_back(siz - 1);
    }
    void BFS() {
        for (int i = 1; i <= n; i++) dis[i] = n;
        queue<int> que;
        que.push(t);
        dis[t] = 0;
        while (que.size()) {
            int u = que.front();
            que.pop();
            for (int i = 0; i < G[u].size(); i++) {
                Edge &e = edge[G[u][i]];
                if (e.cap <= e.flow && dis[e.v] == n) {
                    que.push(e.v);
                    dis[e.v] = dis[u] + 1;
                }
            }
        }
    }
    ll Augment() {
        ll x = t, a = 0x3f3f3f3f;
        while (x != s) {
            Edge &e = edge[p[x]];
            a       = min(a, e.cap - e.flow);
            x       = edge[p[x]].u;
        }
        x = t;
        while (x != s) {
            edge[p[x]].flow += a;
            edge[p[x] ^ 1].flow -= a;
            x = edge[p[x]].u;
        }
        return a;
    }
    ll MaxFlow() {
        ll flow = 0LL;
        ///bfs();//wa
        BFS();//ac
        memset(num, 0, sizeof num);
        for (int i = 0; i <= n; i++) num[dis[i]]++;
        int x = s;
        memset(cur, 0, sizeof cur);
        while (dis[s] < n) {
            if (x == t) {
                flow += Augment();
                x = s;
            }
            int ok = 0;
            for (int i = cur[x]; i < G[x].size(); i++) {
                Edge &e = edge[G[x][i]];
                if (e.cap > e.flow && dis[x] == dis[e.v] + 1) {
                    ok     = 1;
                    p[e.v] = G[x][i];
                    cur[x] = i;
                    x      = e.v;
                    break;
                }
            }
            if (!ok) {
                ll m = n - 1;
                for (int i = 0; i < G[x].size(); i++) {
                    Edge &e = edge[G[x][i]];
                    if (e.cap > e.flow) m = min(m, dis[e.v]);
                }
                if (--num[dis[x]] == 0) break;
                num[dis[x] = m + 1]++;
                cur[x] = 0;
                if (x != s) x = edge[p[x]].u;
            }
        }
        return flow;
    }
} solve;
int main() {
    int n = read, m = read, s = read, t = read;
    solve.init(n, s, t);
    for (int i = 1; i <= m; i++) {
        int u = read, v = read;
        ll cap = read;
        solve.add(u, v, cap);
    }
    cout << solve.MaxFlow() << 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代码实现)