Algorithm 网络流最大流(代码)(Edmond-Karp算法)

本文详细介绍了Ford-Fulkerson算法及其在寻找网络最大流的应用。通过使用预处理数组PRE来记录增广路径上的节点前驱,提高了算法的时间效率。文章还提供了具体的伪代码,并解释了如何利用广度优先搜索(BFS)来寻找增广路径。
这里有用到了PRE的数组,该数组的作用和静态邻接表的原理是一样的。能减少时间复杂度。
详细的解释在上篇文章写到了。
i
nt c[MAX][MAX];  //残留网络容量
int pre[MAX];  //保存增广路径上的点的前驱顶点
bool visit[MAX];

int Ford_Fulkerson(int src,int des,intn){   //src:源点 des:汇点n:顶点个数
    int i,_min,total=0;
    while(true){
        if(!Edmonds_Karp(src,des,n))return total;//如果找不到增广路就返回,在具体实现时替换函数名
        _min=(1<<30);
        i=des;
        while(i!=src){  //通过pre数组查找增广路径上的边,求出残留容量的最小值
            if(_min>c[pre[i]][i])_min=c[pre[i]][i];
            i=pre[i];
        }
        i=des;
        while(i!=src){   //再次遍历,更新增广路径上边的流值
            c[pre[i]][i]-=_min;
            c[i][pre[i]]+=_min;
            i=pre[i];
        }
        total+=_min;    //每次加上更新的值
    }
}
bool Edmonds_Karp(int src,int des,int n){
    int v,i;
    for(i=0;i
    front=rear=0;    //初始化
    que[rear++]=src;
    visit[src]=true;
    while(front!=rear){    //将源点进队后开始广搜的操作
        v=que[front++];
        //这里如果采用邻接表的链表实现会有更好的效率,但是要注意(u,v)或(v,u)有任何一条
        //边存在于原网络流中,那么邻接表中既要包含(u,v)也要包含(v,u)
        for(i=0;i
            if(!visit[i]&&c[v][i]){ //只有残留容量大于0时才存在边
                que[rear++]=i;
                visit[i]=true;
                pre[i]=v;
                if(i==des)return true;  //如果已经到达汇点,说明存在增广路径返回true
            }
        }
    }
    return false;
}

### Edmonds-Karp Algorithm for Maximum Flow in Graph G Edmonds-Karp算法是Ford-Fulkerson方法的一种具体实现,它通过使用广度优先搜索(BFS)来寻找增广路径,从而确保找到的路径是最短路径。以下是基于Edmonds-Karp算法求解图G最大流问题的具体实现[^1]。 #### 算法步骤描述 1. 初始化流量为0。 2. 构建残留网络,并使用BFS从源节点到汇节点寻找增广路径。 3. 如果存在增广路径,则计算该路径上的最小残留容量,并更新残留网络中的流量。 4. 重复上述过程,直到无法找到新的增广路径。 #### Python 实现代码 以下是一个基于Python的Edmonds-Karp算法实现: ```python from collections import defaultdict, deque def edmonds_karp(graph, source, sink): parent = defaultdict(lambda: -1) # 存储路径信息 max_flow = 0 # 最大流初始化为0 # BFS函数:用于寻找增广路径 def bfs(): visited = set() queue = deque([source]) visited.add(source) while queue: u = queue.popleft() for v, capacity in graph[u].items(): if v not in visited and capacity > 0: queue.append(v) visited.add(v) parent[v] = u if v == sink: return True return False # 主循环:不断寻找增广路径并更新流量 while bfs(): path_flow = float('Inf') s = sink while s != source: path_flow = min(path_flow, graph[parent[s]][s]) # 找到路径上的最小容量 s = parent[s] max_flow += path_flow # 更新残留网络 v = sink while v != source: u = parent[v] graph[u][v] -= path_flow # 减少正向边的容量 graph[v][u] += path_flow # 增加反向边的容量 v = parent[v] return max_flow # 示例图G的构建 graph = { 's': {'a': 16, 'b': 13}, 'a': {'b': 10, 'c': 12}, 'b': {'d': 4}, 'c': {'t': 20, 'b': 9}, 'd': {'c': 7, 't': 4}, 't': {} } source = 's' sink = 't' # 调用Edmonds-Karp算法 max_flow = edmonds_karp(graph, source, sink) print(f"最大流为: {max_flow}") ``` #### 关键点解释 - **残留网络**:在每次迭代中,都会根据当前的流量更新残留网络,以反映剩余可用容量[^5]。 - **增广路径**:通过BFS找到从源节点到汇节点的最短路径,确保算法的时间复杂度较低[^1]。 - **流量更新**:对于每条增广路径,计算其最小残留容量,并更新所有相关边的容量。 #### 时间复杂度 Edmonds-Karp算法的时间复杂度为 \(O(VE^2)\),其中 \(V\) 是图中的节点数,\(E\) 是边数。这是因为每次BFS的时间复杂度为 \(O(E)\),而最多需要执行 \(O(VE)\) 次BFS操作[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值