@@ -1368,3 +1368,134 @@ def dfs(u):
1368
1368
bridges .append ((b , a ))
1369
1369
bridges .sort ()
1370
1370
return bridges
1371
+
1372
+ def _find_path_dfs (graph , s , t , flow_pass ):
1373
+ """
1374
+ Finds an augmenting path in a flow network using Depth-First Search (DFS).
1375
+
1376
+ Parameters
1377
+ ==========
1378
+ graph : Graph
1379
+ The flow network graph.
1380
+ s : str
1381
+ The source node.
1382
+ t : str
1383
+ The sink node.
1384
+ flow_pass : dict
1385
+ A dictionary tracking the flow passed through each edge.
1386
+
1387
+ Returns
1388
+ ==========
1389
+ tuple
1390
+ A tuple containing the path flow and a dictionary of parent nodes.
1391
+
1392
+ Example
1393
+ ========
1394
+ >>> graph = Graph(implementation='adjacency_list')
1395
+ >>> graph.add_edge('s', 'o', 3)
1396
+ >>> graph.add_edge('s', 'p', 3)
1397
+ >>> graph.add_edge('o', 'p', 2)
1398
+ >>> graph.add_edge('o', 'q', 3)
1399
+ >>> graph.add_edge('p', 'r', 2)
1400
+ >>> graph.add_edge('r', 't', 3)
1401
+ >>> graph.add_edge('q', 'r', 4)
1402
+ >>> graph.add_edge('q', 't', 2)
1403
+ >>> flow_passed = {}
1404
+ >>> path_flow, parent = _find_path_dfs(graph, 's', 't', flow_passed)
1405
+ """
1406
+
1407
+ visited = {}
1408
+ stack = Stack ()
1409
+ parent = {}
1410
+
1411
+ stack .appendd (s )
1412
+ visited [s ] = True
1413
+
1414
+ while stack :
1415
+ curr = stack .pop ()
1416
+
1417
+ if curr == t :
1418
+ break
1419
+
1420
+ for i in graph .i (curr ):
1421
+ i_name = i .name
1422
+ capacity = graph .get_edge (curr , i_name ).value
1423
+ flow = flow_pass .get ((curr , i_name ), 0 )
1424
+
1425
+ if i not in visited and capacity - flow > 0 :
1426
+ visited [i_name ] = True
1427
+ parent [i_name ] = curr
1428
+ stack .append (i_name )
1429
+
1430
+ if t not in parent and t != s :
1431
+ return 0 , {}
1432
+
1433
+ curr = t
1434
+ path_flow = float ('inf' )
1435
+ if t == s :
1436
+ return 0 , {}
1437
+ while curr != s :
1438
+ prev = parent [curr ]
1439
+ capacity = graph .get_edge (prev , curr ).value
1440
+ flow = flow_pass .get ((prev , curr ), 0 )
1441
+ path_flow = min (path_flow , capacity - flow )
1442
+ curr = prev
1443
+
1444
+ return path_flow , parent
1445
+
1446
+ def _max_flow_ford_fulkerson_ (graph , s , t ):
1447
+ """
1448
+ Computes the maximum flow in a flow network using the Ford-Fulkerson algorithm.
1449
+
1450
+ Parameters
1451
+ ==========
1452
+ graph : Graph
1453
+ The flow network graph.
1454
+ s : str
1455
+ The source node.
1456
+ t : str
1457
+ The sink node.
1458
+
1459
+ Returns
1460
+ ==========
1461
+ int
1462
+ The maximum flow from the source to the sink.
1463
+
1464
+ Example
1465
+ ========
1466
+ >>> graph = Graph(implementation='adjacency_list')
1467
+ >>> graph.add_edge('s', 'o', 3)
1468
+ >>> graph.add_edge('s', 'p', 3)
1469
+ >>> graph.add_edge('o', 'p', 2)
1470
+ >>> graph.add_edge('o', 'q', 3)
1471
+ >>> graph.add_edge('p', 'r', 2)
1472
+ >>> graph.add_edge('r', 't', 3)
1473
+ >>> graph.add_edge('q', 'r', 4)
1474
+ >>> graph.add_edge('q', 't', 2)
1475
+ >>> max_flow = _max_flow_ford_fulkerson_(graph, 's', 't')
1476
+ """
1477
+
1478
+ if s not in graph .vertices or t not in graph .vertices :
1479
+ raise ValueError ("Source or sink not in graph." )
1480
+
1481
+ ans = 0
1482
+ flow_pass = {}
1483
+
1484
+ while True :
1485
+ path_flow , parent = _find_path_dfs (graph , s , t , flow_pass )
1486
+
1487
+ if path_flow <= 0 :
1488
+ break
1489
+
1490
+ ans += path_flow
1491
+
1492
+ curr = t
1493
+ while curr != s :
1494
+ pre = parent [curr ]
1495
+ fp = flow_pass .get ((pre , curr ), 0 )
1496
+ flow_pass [(pre , curr )] = fp + path_flow
1497
+ fp = flow_pass .get ((curr , pre ), 0 )
1498
+ flow_pass [(curr , pre )] = fp - path_flow
1499
+ curr = pre
1500
+
1501
+ return ans
0 commit comments