最大流__EdmondsKarp算法

本文深入探讨了Edmonds-Karp算法,一种用于求解最大流问题的有效方法。通过实例展示了如何利用该算法解决disjoint-paths和network-connectivity问题,并详细解释了BFS_EK在算法中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<iostream>
#include<queue>
using std::cin;
using std::queue;
const int size = 201;

int Gf[size][size] = {0};
int pre[size] = {0};
int visited[size] = {0};
int n,m;

int BFS(int src,int des)
{
    for(int i = 0;i <= n;i++){visited[i] = 0; pre[i] = 0;}
    queue<int>my_queue;
    my_queue.push(src);
    visited[src] = 1;
    int flow = 0x7FFFFFFF;

    while(!my_queue.empty())
    {
        int u = my_queue.front();
        my_queue.pop();

        for(int i = 1;i <= n;i++)
        {
            if(i != u && visited[i] == 0 && Gf[u][i] > 0)
            {
                pre[i] = u;
                visited[i] = 1;
                my_queue.push(i);
                flow = Gf[u][i] > flow ? flow : Gf[u][i];

            }
        }
    }
    if(pre[des])
        return flow;
    return 0;
}

int main(int argc, const char** argv) {

    cin>>n>>m;
    for(int i = 0; i < m;i++)
    {
        int x,y,w;
        cin>>x>>y>>w;
        Gf[x][y] = w;
    }

    int sum = 0;

    int increasement = 0;
    while( (increasement = BFS(1,n) ) != 0)
    {
        int temp = n;
        while(temp != 1)
        {
            int Pi = pre[temp];
            Gf[Pi][temp] -= increasement;
            Gf[temp][Pi] += increasement;
            temp = Pi;
        }
        sum += increasement;
    }

    std::cout << "max flow: "<<sum << std::endl;
    return 0;
}

一、实验目标

利用Edmonds-Karp算法解决disjoint-paths和edge-connectivity问题

二、实验设计

disjoint-paths

不相交路径的数量在直观上看来就是从src到des完全不同的路径的数量之和

将图中每一个边的容量记为1的话,最大流的值即为disjoint-paths的解

network-connectivity

将每一个边的容量记为1

根据定义,network-connectivity要找的其实就是最小割的值

根据最大流最小割定理,最小割的值就是最大流的值,所以最大流的值就是network-connectivity的解

综上所述,上述两个问题的解答是求最大流的过程

Edmonds-Karp算法

  • 图中所有的边的流全部置为0
  • 在剩余网络上利用BFS寻找增广路径
    • 选取剩余网络中从s到t的路径中最短的一条路径作为增广路径(假设所有边的权重为1)
    • 记录增广路径中流值最小边的流值
      • 更新剩余网络中的边的流值
      • 增加图中最大流的值
cin>>n>>m;
    for(int i = 0; i < m;i++)
    {
        int x,y,w;
        cin>>x>>y>>w;
        Gf[x][y] = w;
    }

    int sum = 0;

    int increasement = 0;
    while( (increasement = BFS(1,n) ) != 0)
    {
        int temp = n;
        while(temp != 1)
        {
            int Pi = pre[temp];
            Gf[Pi][temp] -= increasement;
            Gf[temp][Pi] += increasement;
            temp = Pi;
        }
        sum += increasement;
    }

BFS_EK

  • 与基础的BFS相比,还需记录路径中流值最小边的流值并返回
int BFS(int src,int des)
{
    for(int i = 0;i <= n;i++){visited[i] = 0; pre[i] = 0;}
    queue<int>my_queue;
    my_queue.push(src);
    visited[src] = 1;
    int flow = 0x7FFFFFFF;

    while(!my_queue.empty())
    {
        int u = my_queue.front();
        my_queue.pop();

        for(int i = 1;i <= n;i++)
        {
            if(i != u && visited[i] == 0 && Gf[u][i] > 0)
            {
                pre[i] = u;
                visited[i] = 1;
                my_queue.push(i);
                flow = Gf[u][i] > flow ? flow : Gf[u][i];

            }
        }
    }
    if(pre[des])
        return flow;
    return 0;
}

### 网络流算法及其最大流最小割的应用 #### 最大流最小割基本概念 在网络流理论中,最大流最小割是一个核心的概念。它描述了一个网络中从源点 \( S \) 到汇点 \( T \) 的最大可能流量与该网络的最小割之间的关系。具体来说,最大流的值等于最小割的容量之和[^1]。 #### 数学定义与定理解释 最大流最小割定理指出,在任何网络中,能够从源点传输到汇点的最大流量等于移除某些特定边后使整个网络断开所需的这些边的总容量。换句话说,通过计算网络中的最大流,可以直接获得其对应的最小割[^4]。 #### MATLAB 实现最大流最小割算法 在实际操作层面,MATLAB 提供了一种有效的方法来解决这一类问题。以下是基于 Edmonds-Karp 或 Ford-Fulkerson 方法的一个简单实现: ```matlab function maxFlow = edmondsKarp(capacity, source, sink) n = size(capacity, 1); flow = zeros(n); while true % 使用 BFS 寻找增广路径 parent = zeros(1, n); queue = []; visited = false(1, n); queue = [queue, source]; visited(source) = true; foundPath = false; while ~isempty(queue) && ~foundPath u = queue(1); queue(1) = []; for v = 1:n if ~visited(v) && (capacity(u,v) - flow(u,v)) > 0 queue = [queue, v]; parent(v) = u; visited(v) = true; if v == sink foundPath = true; break; end end end end if ~foundPath break; % 如果找不到增广路径,则结束循环 end pathFlow = inf; s = sink; while s ~= source pathFlow = min(pathFlow, capacity(parent(s),s) - flow(parent(s),s)); s = parent(s); end t = sink; while t ~= source flow(parent(t),t) = flow(parent(t),t) + pathFlow; flow(t,parent(t)) = flow(t,parent(t)) - pathFlow; t = parent(t); end end maxFlow = sum(flow(source,:)); % 计算从源节点流出的总流量作为最大流 end ``` 上述代码实现了经典的 Edmonds-Karp 算法用于寻找给定图上的最大流[^2]。 #### 应用场景分析 最大流最小割不仅限于理论上探讨,还广泛应用于多个领域,比如交通规划、计算机视觉中的图像分割以及通信网络设计等。例如,在图像处理方面,可以通过构建合适的二分图并应用最大流/最小割技术来进行前景背景分离[^3]。 #### 总结 综上所述,理解并掌握最大流最小割原理对于深入学习图论及相关算法至关重要。无论是学术研究还是工业实践,这项技能都有着不可替代的价值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值