dinic网络流算法CPP

#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;

// 边的数据结构
struct Edge {
    int from, to, capacity, flow;
};

// Dinic 算法类
class Dinic {
private:
    int n;  // 图中节点的数量
    vector<vector<int>> adj;  // 邻接表,存储图的结构
    vector<Edge> edges;  // 存储所有边的信息
    vector<int> dist;  // 存储节点的层级距离
    vector<int> ptr;  // 指针,标记从每个节点开始查找增广路径时遍历到的边的位置
    
    // 利用 BFS 构建分层图
    bool buildLevelGraph(int source, int sink) {
        fill(dist.begin(), dist.end(), -1);  // 初始化节点的层级距离为-1
        queue<int> q;
        q.push(source);
        dist[source] = 0;  // 源节点的层级距离为0
        
        while (!q.empty()) {
            int curr = q.front();
            q.pop();
            
            for (int i = 0; i < adj[curr].size(); i++) {
                int edgeIdx = adj[curr][i];  // 当前边在 edges 中的索引
                Edge& e = edges[edgeIdx];
                
                if (dist[e.to] == -1 && e.flow < e.capacity) {
                    // 当前边的终点未标记层级且还可以增加流量,则加入分层图
                    dist[e.to] = dist[curr] + 1;
                    q.push(e.to);
                }
            }
        }
        
        return (dist[sink] != -1);  // 若汇节点的层级距离不为-1,则存在增广路径
    }
    
    // 在分层图上寻找增广路径,并增加流量
    int findAugmentingPath(int curr, int sink, int minCapacity) {
        if (curr == sink)
            return minCapacity;  // 到达汇节点,返回流量增加的最小值
        
        while (ptr[curr] < adj[curr].size()) {
            int edgeIdx = adj[curr][ptr[curr]];  // 当前边在 edges 中的索引
            Edge& e = edges[edgeIdx];
            
            if (dist[e.to] == dist[curr] + 1 && e.flow < e.capacity) {
                // 下一个节点的层级等于当前节点层级+1,并且当前边还可以增加流量
                int bottleneck = findAugmentingPath(e.to, sink, min(minCapacity, e.capacity - e.flow));
                
                if (bottleneck > 0) {
                    // 更新当前边的流量和反向边的流量
                    e.flow += bottleneck;
                    edges[edgeIdx ^ 1].flow -= bottleneck;
                    return bottleneck;
                }
            }
            
            ptr[curr]++;
        }
        
        return 0;  // 没有找到增广路径,返回0
    }
    
public:
    Dinic(int numNodes) {
        n = numNodes;
        adj.resize(n);
        dist.resize(n);
        ptr.resize(n);
    }
    
    // 添加一条边到图中
    void addEdge(int from, int to, int capacity) {
        // 正向边
        edges.push_back({from, to, capacity, 0});
        adj[from].push_back(edges.size() - 1);
        
        // 反向边,流量为0,容量为0
        edges.push_back({to, from, 0, 0});
        adj[to].push_back(edges.size() - 1);
    }
    
    // 计算最大流
    int maxFlow(int source, int sink) {
        int totalFlow = 0;
        
        while (buildLevelGraph(source, sink)) {
            fill(ptr.begin(), ptr.end(), 0);  // 初始化指针 ptr
            
            while (int bottleneck = findAugmentingPath(source, sink, INT_MAX)) {
                totalFlow += bottleneck;
            }
        }
        
        return totalFlow;
    }
};

int main() {
    int numNodes = 4;  // 图中节点的数量
    Dinic dinic(numNodes);
    
    // 添加边到图中
    dinic.addEdge(0, 1, 3);
    dinic.addEdge(0, 2, 2);
    dinic.addEdge(1, 2, 2);
    dinic.addEdge(1, 3, 3);
    dinic.addEdge(2, 3, 3);
    
    int source = 0;  // 源节点
    int sink = 3;  // 汇节点
    
    int maxFlow = dinic.maxFlow(source, sink);
    
    cout << "Maximum flow: " << maxFlow << endl;
    
    return 0;
}

同时可以参考 博客 https://www.cnblogs.com/SYCstudio/p/7260613.html的讲解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值