Skip to content

Commit 906c985

Browse files
danielx285cclauss
authored andcommitted
Create dinic.py (#1396)
* Create dinic.py Dinic's algorithm for maximum flow * Update dinic.py Changes made.
1 parent 7444a1f commit 906c985

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

graphs/dinic.py

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
INF = float("inf")
2+
3+
class Dinic:
4+
def __init__(self, n):
5+
self.lvl = [0] * n
6+
self.ptr = [0] * n
7+
self.q = [0] * n
8+
self.adj = [[] for _ in range(n)]
9+
10+
'''
11+
Here we will add our edges containing with the following parameters:
12+
vertex closest to source, vertex closest to sink and flow capacity
13+
through that edge ...
14+
'''
15+
def add_edge(self, a, b, c, rcap=0):
16+
self.adj[a].append([b, len(self.adj[b]), c, 0])
17+
self.adj[b].append([a, len(self.adj[a]) - 1, rcap, 0])
18+
19+
#This is a sample depth first search to be used at max_flow
20+
def depth_first_search(self, vertex, sink, flow):
21+
if vertex == sink or not flow:
22+
return flow
23+
24+
for i in range(self.ptr[vertex], len(self.adj[vertex])):
25+
e = self.adj[vertex][i]
26+
if self.lvl[e[0]] == self.lvl[vertex] + 1:
27+
p = self.depth_first_search(e[0], sink, min(flow, e[2] - e[3]))
28+
if p:
29+
self.adj[vertex][i][3] += p
30+
self.adj[e[0]][e[1]][3] -= p
31+
return p
32+
self.ptr[vertex] = self.ptr[vertex] + 1
33+
return 0
34+
35+
#Here we calculate the flow that reaches the sink
36+
def max_flow(self, source, sink):
37+
flow, self.q[0] = 0, source
38+
for l in range(31): # l = 30 maybe faster for random data
39+
while True:
40+
self.lvl, self.ptr = [0] * len(self.q), [0] * len(self.q)
41+
qi, qe, self.lvl[source] = 0, 1, 1
42+
while qi < qe and not self.lvl[sink]:
43+
v = self.q[qi]
44+
qi += 1
45+
for e in self.adj[v]:
46+
if not self.lvl[e[0]] and (e[2] - e[3]) >> (30 - l):
47+
self.q[qe] = e[0]
48+
qe += 1
49+
self.lvl[e[0]] = self.lvl[v] + 1
50+
51+
p = self.depth_first_search(source, sink, INF)
52+
while p:
53+
flow += p
54+
p = self.depth_first_search(source, sink, INF)
55+
56+
if not self.lvl[sink]:
57+
break
58+
59+
return flow
60+
61+
#Example to use
62+
63+
'''
64+
Will be a bipartite graph, than it has the vertices near the source(4)
65+
and the vertices near the sink(4)
66+
'''
67+
#Here we make a graphs with 10 vertex(source and sink includes)
68+
graph = Dinic(10)
69+
source = 0
70+
sink = 9
71+
'''
72+
Now we add the vertices next to the font in the font with 1 capacity in this edge
73+
(source -> source vertices)
74+
'''
75+
for vertex in range(1, 5):
76+
graph.add_edge(source, vertex, 1)
77+
'''
78+
We will do the same thing for the vertices near the sink, but from vertex to sink
79+
(sink vertices -> sink)
80+
'''
81+
for vertex in range(5, 9):
82+
graph.add_edge(vertex, sink, 1)
83+
'''
84+
Finally we add the verices near the sink to the vertices near the source.
85+
(source vertices -> sink vertices)
86+
'''
87+
for vertex in range(1, 5):
88+
graph.add_edge(vertex, vertex+4, 1)
89+
90+
#Now we can know that is the maximum flow(source -> sink)
91+
print(graph.max_flow(source, sink))
92+
93+

0 commit comments

Comments
 (0)