MaxFlow/gpt/code.md
2024-12-17 16:53:26 +08:00

116 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

好的,以下是使用 **Dinic's Algorithm** 实现最大流问题的 Python 代码。Dinic 算法比 Edmonds-Karp 更高效,尤其是在稀疏图中。它使用分层网络和每一层的增广路径来提高效率。
### **Dinic算法的Python实现**
```python
from collections import deque
class MaxFlow:
def __init__(self, vertices):
self.V = vertices # 图的顶点数
self.graph = [[] for _ in range(vertices)] # 邻接表表示图
self.level = [-1] * vertices # 层次标记
self.ptr = [0] * vertices # 每个节点在其邻接边中的指针
def add_edge(self, u, v, capacity):
"""添加从u到v的边并反向边的容量初始化为0"""
self.graph[u].append([v, capacity, len(self.graph[v])]) # (目标点, 容量, 反向边的索引)
self.graph[v].append([u, 0, len(self.graph[u]) - 1]) # (源点, 容量0, 反向边的索引)
def bfs(self, source, sink):
"""BFS进行分层图构建"""
queue = deque([source])
self.level = [-1] * self.V
self.level[source] = 0
while queue:
u = queue.popleft()
for v, cap, _ in self.graph[u]:
if self.level[v] == -1 and cap > 0: # 未访问且容量大于0
self.level[v] = self.level[u] + 1
if v == sink:
return True
queue.append(v)
return False
def dfs(self, u, sink, flow):
"""DFS寻找增广路径并更新残余图"""
if u == sink:
return flow
while self.ptr[u] < len(self.graph[u]):
v, cap, rev = self.graph[u][self.ptr[u]]
if self.level[v] == self.level[u] + 1 and cap > 0:
current_flow = min(flow, cap)
result = self.dfs(v, sink, current_flow)
if result > 0:
# 更新正向边和反向边
self.graph[u][self.ptr[u]][1] -= result
self.graph[v][rev][1] += result
return result
self.ptr[u] += 1
return 0
def dinic(self, source, sink):
"""Dinic算法计算最大流"""
max_flow = 0
while self.bfs(source, sink):
self.ptr = [0] * self.V
while True:
flow = self.dfs(source, sink, float('Inf'))
if flow == 0:
break
max_flow += flow
return max_flow
# 示例
if __name__ == "__main__":
vertices = 6
g = MaxFlow(vertices)
# 添加边及其容量
g.add_edge(0, 1, 16)
g.add_edge(0, 2, 13)
g.add_edge(1, 2, 10)
g.add_edge(1, 3, 12)
g.add_edge(2, 1, 4)
g.add_edge(2, 4, 14)
g.add_edge(3, 2, 9)
g.add_edge(3, 5, 20)
g.add_edge(4, 3, 7)
g.add_edge(4, 5, 4)
source = 0 # 源点
sink = 5 # 汇点
max_flow = g.dinic(source, sink)
print("最大流为:", max_flow)
```
### **代码解释:**
1. **添加边:** `add_edge(u, v, capacity)` 方法将一条从节点 `u``v` 的边加入图中,且边的容量为 `capacity`。同时,在反向边上初始化容量为 0。
2. **BFS层次图构建** `bfs(source, sink)` 方法通过广度优先搜索构建分层网络,标记每个节点的层次,帮助找增广路径。
3. **DFS增广路径** `dfs(u, sink, flow)` 方法通过深度优先搜索,在层次网络中寻找增广路径并进行流量传递。
4. **Dinic算法** `dinic(source, sink)` 方法利用层次图和增广路径相结合的方式进行多轮流量增广,直到没有更多增广路径为止。
### **算法分析:**
1. **时间复杂度:**
- 每轮BFS的时间复杂度为 \(O(V + E)\)
- 每轮DFS的时间复杂度为 \(O(E)\)。
- 总体时间复杂度为 \(O(V^2 E)\)在稀疏图中相较于Edmonds-Karp更为高效。
2. **空间复杂度:**
- 使用了邻接表来表示图,空间复杂度为 \(O(V + E)\)其中V为节点数E为边数。
### **实验输出:**
运行代码后,输出的最大流值如下:
```
最大流为: 23
```
### **总结:**
使用 Dinic 算法可以在稀疏图中高效计算最大流,比 Edmonds-Karp 更加高效尤其在实际问题中当图的边数和顶点数较大时Dinic 算法的表现尤为突出。
如果有任何问题或者需要进一步的解释,随时告诉我!